diff --git a/CUETools.Codecs.FLAKE/Flake.cs b/CUETools.Codecs.FLAKE/Flake.cs index 724e098..3db732d 100644 --- a/CUETools.Codecs.FLAKE/Flake.cs +++ b/CUETools.Codecs.FLAKE/Flake.cs @@ -149,10 +149,11 @@ namespace CUETools.Codecs.FLAKE public uint obits; public uint wbits; public int* samples; - public fixed uint done_lpcs[lpc.MAX_LPC_WINDOWS * 2]; + public fixed uint done_lpcs[lpc.MAX_LPC_WINDOWS * lpc.MAX_LPC_PRECISIONS]; public uint done_fixed; - public fixed double lpcs_reff[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_WINDOWS]; - public fixed int lpcs_order[lpc.MAX_LPC_WINDOWS]; + public fixed double reflection_coeffs[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_WINDOWS]; + public fixed double autocorr_values[(lpc.MAX_LPC_ORDER + 1) * lpc.MAX_LPC_WINDOWS]; + public fixed int autocorr_orders[lpc.MAX_LPC_WINDOWS]; }; unsafe struct FlacFrame @@ -174,8 +175,7 @@ namespace CUETools.Codecs.FLAKE Estimate = 1, LogFast = 2, LogSearch = 3, - EstSearch = 4, - Estimate8 = 6, + EstSearch2 = 4, Search = 5 } diff --git a/CUETools.Codecs.FLAKE/FlakeWriter.cs b/CUETools.Codecs.FLAKE/FlakeWriter.cs index d000033..677bd39 100644 --- a/CUETools.Codecs.FLAKE/FlakeWriter.cs +++ b/CUETools.Codecs.FLAKE/FlakeWriter.cs @@ -255,14 +255,25 @@ namespace CUETools.Codecs.FLAKE set { eparams.stereo_method = value; } } - public int MaxPrecisionSearch + public int MinPrecisionSearch { - get { return eparams.lpc_precision_search; } + get { return eparams.lpc_min_precision_search; } set { - if (value < 0 || value > 1) + if (value < 0 || value > eparams.lpc_max_precision_search) + throw new Exception("unsupported MinPrecisionSearch value"); + eparams.lpc_min_precision_search = value; + } + } + + public int MaxPrecisionSearch + { + get { return eparams.lpc_max_precision_search; } + set + { + if (value < eparams.lpc_min_precision_search || value >= lpc.MAX_LPC_PRECISIONS) throw new Exception("unsupported MaxPrecisionSearch value"); - eparams.lpc_precision_search = value; + eparams.lpc_max_precision_search = value; } } @@ -350,12 +361,26 @@ namespace CUETools.Codecs.FLAKE } set { - if (value > 32 || value < eparams.min_prediction_order) + if (value > lpc.MAX_LPC_ORDER || value < eparams.min_prediction_order) throw new Exception("invalid MaxLPCOrder " + value.ToString()); eparams.max_prediction_order = value; } } + public int EstimationDepth + { + get + { + return eparams.estimation_depth; + } + set + { + if (value > 32 || value < 1) + throw new Exception("invalid estimation_depth " + value.ToString()); + eparams.estimation_depth = value; + } + } + public int MinFixedOrder { get @@ -559,11 +584,11 @@ namespace CUETools.Codecs.FLAKE frame->subframes[ch].best.residual = r; frame->subframes[ch].best.type = SubframeType.Verbatim; frame->subframes[ch].best.size = UINT32_MAX; - for (int iWindow = 0; iWindow < 2 * lpc.MAX_LPC_WINDOWS; iWindow++) + for (int iWindow = 0; iWindow < lpc.MAX_LPC_PRECISIONS * lpc.MAX_LPC_WINDOWS; iWindow++) frame->subframes[ch].done_lpcs[iWindow] = 0; frame->subframes[ch].done_fixed = 0; for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++) - frame->subframes[ch].lpcs_order[iWindow] = 0; + frame->subframes[ch].autocorr_orders[iWindow] = 0; } unsafe static void channel_decorrelation(int* leftS, int* rightS, int *leftM, int *rightM, int blocksize) @@ -767,13 +792,13 @@ namespace CUETools.Codecs.FLAKE else if (frame->blocksize <= 16384) lpc_precision = 14U; else lpc_precision = 15; - for (uint i_precision = 0; i_precision <= eparams.lpc_precision_search && lpc_precision + i_precision < 16; i_precision++) + 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].done_lpcs[iWindow + i_precision * lpc.MAX_LPC_WINDOWS] & (1U << (order - 1))) == 0) + if ((frame->subframes[ch].done_lpcs[iWindow + i_precision * lpc.MAX_LPC_WINDOWS] & (1U << (order - 1))) == 0) { frame->subframes[ch].done_lpcs[iWindow + i_precision * lpc.MAX_LPC_WINDOWS] |= (1U << (order - 1)); - uint cbits = lpc_precision + i_precision; + uint cbits = lpc_precision + (uint)i_precision; frame->current.type = SubframeType.LPC; frame->current.order = order; @@ -819,10 +844,32 @@ namespace CUETools.Codecs.FLAKE choose_best_subframe(frame, ch); } - unsafe void encode_residual(FlacFrame* frame, int ch, PredictionType predict, OrderMethod omethod) + unsafe static bool is_interesting_order(double* reff, int order, int max_order) + { + return (order > 4 && Math.Abs(reff[order - 1]) >= 0.10 && (order == max_order || Math.Abs(reff[order]) < 0.10)) || + (order < 6 && order < max_order - 1 && reff[order + 1] * reff[order + 1] + reff[order] * reff[order] < 0.1); + } + + unsafe double* get_reflection_coeffs(FlacFrame* frame, int ch, int order, int iWindow) + { + double* reff = frame->subframes[ch].reflection_coeffs + iWindow * lpc.MAX_LPC_ORDER; + if (frame->subframes[ch].autocorr_orders[iWindow] > order) + return reff; + double* autoc = frame->subframes[ch].autocorr_values + iWindow * (lpc.MAX_LPC_ORDER + 1); + lpc.compute_autocorr(frame->subframes[ch].samples, (uint)frame->blocksize, + (uint)frame->subframes[ch].autocorr_orders[iWindow], + (uint)order, autoc, frame->window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2); + lpc.compute_schur_reflection(autoc, (uint)order, reff); + frame->subframes[ch].autocorr_orders[iWindow] = order + 1; + return reff; + } + + unsafe void encode_residual(FlacFrame* frame, int ch, PredictionType predict, OrderMethod omethod, int pass) { int* smp = frame->subframes[ch].samples; int i, n = frame->blocksize; + // save best.window, because we can overwrite it later with fixed frame + int best_window = frame->subframes[ch].best.type == SubframeType.LPC ? frame->subframes[ch].best.window : -1; // CONSTANT for (i = 1; i < n; i++) @@ -847,8 +894,9 @@ namespace CUETools.Codecs.FLAKE // FIXED if (predict == PredictionType.Fixed || - predict == PredictionType.Search || - (predict == PredictionType.Estimated && frame->subframes[ch].best.type == SubframeType.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); @@ -861,8 +909,10 @@ namespace CUETools.Codecs.FLAKE // LPC if (n > eparams.max_prediction_order && (predict == PredictionType.Levinson || - predict == PredictionType.Search || - (predict == PredictionType.Estimated && frame->subframes[ch].best.type == SubframeType.LPC))) + predict == PredictionType.Search) + //predict == PredictionType.Search || + //(pass == 2 && frame->subframes[ch].best.type == SubframeType.LPC)) + ) { //double* lpcs = stackalloc double[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER]; int min_order = eparams.min_prediction_order; @@ -870,41 +920,12 @@ namespace CUETools.Codecs.FLAKE for (int iWindow = 0; iWindow < _windowcount; iWindow++) { - if (predict == PredictionType.Estimated && frame->subframes[ch].best.window != iWindow) + if (pass == 2 && iWindow != best_window) continue; - double* reff = frame->subframes[ch].lpcs_reff + iWindow * lpc.MAX_LPC_ORDER; - if (frame->subframes[ch].lpcs_order[iWindow] != max_order) - { - double* autoc = stackalloc double[lpc.MAX_LPC_ORDER + 1]; - lpc.compute_autocorr(smp, (uint)n, (uint)max_order, autoc, frame->window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2); - lpc.compute_schur_reflection(autoc, (uint)max_order, reff); - frame->subframes[ch].lpcs_order[iWindow] = max_order; - } - - int est_order = 1; - int est_order2 = 1; - if (omethod == OrderMethod.Estimate || omethod == OrderMethod.Estimate8 || omethod == OrderMethod.EstSearch) - { - // Estimate optimal order using reflection coefficients - for (int r = max_order - 1; r >= 0; r--) - if (Math.Abs(reff[r]) > 0.1) - { - est_order = r + 1; - break; - } - for (int r = Math.Min(max_order, 8) - 1; r >= 0; r--) - if (Math.Abs(reff[r]) > 0.1) - { - est_order2 = r + 1; - break; - } - } - else - est_order = max_order; - + double* reff = get_reflection_coeffs(frame, ch, max_order, iWindow); double* lpcs = stackalloc double[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER]; - lpc.compute_lpc_coefs(null, (uint)est_order, reff, lpcs); + lpc.compute_lpc_coefs(null, (uint)max_order, reff, lpcs); switch (omethod) { @@ -913,23 +934,33 @@ namespace CUETools.Codecs.FLAKE encode_residual_lpc_sub(frame, lpcs, iWindow, max_order, ch); break; case OrderMethod.Estimate: - // estimated order - encode_residual_lpc_sub(frame, lpcs, iWindow, est_order, ch); + // estimated orders + // Search at reflection coeff thresholds (where they cross 0.10) + { + int found = 0; + for (i = max_order; i >= min_order && found < eparams.estimation_depth; i--) + if (is_interesting_order(reff, i, max_order)) + { + encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); + found++; + } + if (0 == found) + encode_residual_lpc_sub(frame, lpcs, iWindow, min_order, ch); + } break; - case OrderMethod.Estimate8: - // estimated order - encode_residual_lpc_sub(frame, lpcs, iWindow, est_order2, ch); - break; - //case OrderMethod.EstSearch: - // brute-force search starting from estimate - //encode_residual_lpc_sub(frame, lpcs, iWindow, est_order, ch); - //encode_residual_lpc_sub(frame, lpcs, iWindow, est_order2, ch); - //break; - case OrderMethod.EstSearch: - // brute-force search starting from estimate - for (i = est_order; i >= min_order; i--) - if (i == est_order || Math.Abs(reff[i - 1]) > 0.10) - encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); + case OrderMethod.EstSearch2: + // Search at reflection coeff thresholds (where they cross 0.10) + { + int found = 0; + for (i = min_order; i <= max_order && found < eparams.estimation_depth; i++) + if (is_interesting_order(reff, i, max_order)) + { + encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); + found++; + } + if (0 == found) + encode_residual_lpc_sub(frame, lpcs, iWindow, min_order, ch); + } break; case OrderMethod.Search: // brute-force optimal order search @@ -939,7 +970,6 @@ namespace CUETools.Codecs.FLAKE case OrderMethod.LogFast: // Try max, est, 32,16,8,4,2,1 encode_residual_lpc_sub(frame, lpcs, iWindow, max_order, ch); - //encode_residual_lpc_sub(frame, lpcs, est_order, ch); for (i = lpc.MAX_LPC_ORDER; i >= min_order; i >>= 1) if (i < max_order) encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); @@ -947,7 +977,6 @@ namespace CUETools.Codecs.FLAKE case OrderMethod.LogSearch: // do LogFast first encode_residual_lpc_sub(frame, lpcs, iWindow, max_order, ch); - //encode_residual_lpc_sub(frame, lpcs, est_order, ch); for (i = lpc.MAX_LPC_ORDER; i >= min_order; i >>= 1) if (i < max_order) encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); @@ -974,7 +1003,8 @@ namespace CUETools.Codecs.FLAKE unsafe void output_frame_header(FlacFrame* frame, BitWriter bitwriter) { - bitwriter.writebits(16, 0xFFF8); + 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) @@ -1176,6 +1206,45 @@ namespace CUETools.Codecs.FLAKE window[n] = 0.5 - 0.5 * Math.Cos(2.0 * Math.PI * n / N); } + unsafe void encode_residual_pass1(FlacFrame* frame, int ch) + { + 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.Estimate, 1); + 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 void encode_residual_pass2(FlacFrame* frame, int ch) + { + encode_residual(frame, ch, eparams.prediction_type, eparams.order_method, 2); + } + + unsafe void encode_residual_onepass(FlacFrame* frame, int ch) + { + if (_windowcount > 1) + { + encode_residual_pass1(frame, ch); + encode_residual_pass2(frame, ch); + } else + encode_residual(frame, ch, eparams.prediction_type, eparams.order_method, 0); + } + unsafe void estimate_frame(FlacFrame* frame, bool do_midside) { int subframes = do_midside ? channels * 2 : channels; @@ -1187,32 +1256,17 @@ namespace CUETools.Codecs.FLAKE frame->subframes[ch].best.size = (uint)frame->blocksize * 32 + calc_decorr_score(frame, ch); break; case StereoMethod.Evaluate: + for (int ch = 0; ch < subframes; ch++) { - 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_precision_search = eparams.lpc_precision_search; - int max_partition_order = eparams.max_partition_order; - OrderMethod omethod = OrderMethod.Estimate8; - eparams.min_fixed_order = 2; - eparams.max_fixed_order = 2; - eparams.lpc_precision_search = 0; - if (eparams.max_prediction_order > 12) - eparams.max_prediction_order = 8; - //if (eparams.max_partition_order > 4) - //eparams.max_partition_order = 4; - for (int ch = 0; ch < subframes; ch++) - encode_residual(frame, ch, eparams.prediction_type, omethod); - eparams.min_fixed_order = min_fixed_order; - eparams.max_fixed_order = max_fixed_order; - eparams.max_prediction_order = max_prediction_order; - eparams.lpc_precision_search = lpc_precision_search; - eparams.max_partition_order = max_partition_order; - break; + int windowcount = _windowcount; + _windowcount = 1; + encode_residual_pass1(frame, ch); + _windowcount = windowcount; } + break; case StereoMethod.Search: for (int ch = 0; ch < subframes; ch++) - encode_residual(frame, ch, eparams.prediction_type, eparams.order_method); + encode_residual_onepass(frame, ch); break; } } @@ -1278,12 +1332,16 @@ namespace CUETools.Codecs.FLAKE for (int ch = 0; ch < channels; ch++) { frame->subframes[ch].best.size = UINT32_MAX; - encode_residual(frame, ch, eparams.prediction_type, eparams.order_method); + encode_residual_onepass(frame, ch); } break; case StereoMethod.Evaluate: for (int ch = 0; ch < channels; ch++) - encode_residual(frame, ch, PredictionType.Estimated, eparams.order_method); + { + if (_windowcount > 1) + encode_residual_pass1(frame, ch); + encode_residual_pass2(frame, ch); + } break; case StereoMethod.Search: break; @@ -1343,7 +1401,7 @@ namespace CUETools.Codecs.FLAKE bits_per_sample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); for (int ch = 0; ch < channels; ch++) - encode_residual(&frame, ch, eparams.prediction_type, eparams.order_method); + encode_residual_onepass(&frame, ch); } else { @@ -1819,6 +1877,12 @@ namespace CUETools.Codecs.FLAKE // valid values are 1 to 32 public int max_prediction_order; + // Number of LPC orders to try (for estimate mode) + // set by user prior to calling flake_encode_init + // if set to less than 0, it is chosen based on compression. + // valid values are 1 to 32 + public int estimation_depth; + // minimum fixed prediction order // set by user prior to calling flake_encode_init // if set to less than 0, it is chosen based on compression. @@ -1856,7 +1920,9 @@ namespace CUETools.Codecs.FLAKE // whether to try various lpc_precisions // 0 - use only one precision // 1 - try two precisions - public int lpc_precision_search; + public int lpc_max_precision_search; + + public int lpc_min_precision_search; public WindowFunction window_function; @@ -1882,12 +1948,14 @@ namespace CUETools.Codecs.FLAKE prediction_type = PredictionType.Search; min_prediction_order = 1; max_prediction_order = 8; + estimation_depth = 1; min_fixed_order = 2; max_fixed_order = 2; min_partition_order = 0; max_partition_order = 6; variable_block_size = 0; - lpc_precision_search = 0; + lpc_min_precision_search = 1; + lpc_max_precision_search = 1; do_md5 = true; do_verify = false; do_seektable = true; @@ -1907,55 +1975,37 @@ namespace CUETools.Codecs.FLAKE max_partition_order = 4; break; case 2: - prediction_type = PredictionType.Search; stereo_method = StereoMethod.Independent; window_function = WindowFunction.Welch; max_prediction_order = 12; max_partition_order = 4; break; case 3: - prediction_type = PredictionType.Levinson; - stereo_method = StereoMethod.Evaluate; + stereo_method = StereoMethod.Estimate; window_function = WindowFunction.Welch; - max_partition_order = 4; break; case 4: - prediction_type = PredictionType.Levinson; - stereo_method = StereoMethod.Evaluate; + stereo_method = StereoMethod.Estimate; window_function = WindowFunction.Welch; max_prediction_order = 12; - max_partition_order = 4; break; case 5: - prediction_type = PredictionType.Search; - stereo_method = StereoMethod.Evaluate; window_function = WindowFunction.Welch; max_prediction_order = 12; break; case 6: - prediction_type = PredictionType.Levinson; - stereo_method = StereoMethod.Evaluate; - window_function = WindowFunction.Flattop | WindowFunction.Tukey; + stereo_method = StereoMethod.Estimate; max_prediction_order = 12; break; case 7: - prediction_type = PredictionType.Search; - stereo_method = StereoMethod.Evaluate; - window_function = WindowFunction.Flattop | WindowFunction.Tukey; max_prediction_order = 12; - min_fixed_order = 0; - max_fixed_order = 4; - lpc_precision_search = 1; break; case 8: - prediction_type = PredictionType.Search; - stereo_method = StereoMethod.Evaluate; - window_function = WindowFunction.Flattop | WindowFunction.Tukey; - order_method = OrderMethod.EstSearch; + estimation_depth = 3; max_prediction_order = 12; min_fixed_order = 0; max_fixed_order = 4; - lpc_precision_search = 1; + lpc_max_precision_search = 2; break; case 9: window_function = WindowFunction.Welch; @@ -1965,14 +2015,14 @@ namespace CUETools.Codecs.FLAKE min_fixed_order = 0; max_fixed_order = 4; max_prediction_order = 32; - lpc_precision_search = 0; + //lpc_max_precision_search = 2; break; case 11: - order_method = OrderMethod.EstSearch; min_fixed_order = 0; max_fixed_order = 4; max_prediction_order = 32; - //lpc_precision_search = 1; + estimation_depth = 5; + //lpc_max_precision_search = 2; variable_block_size = 4; break; } diff --git a/CUETools.Codecs.FLAKE/lpc.cs b/CUETools.Codecs.FLAKE/lpc.cs index 57ab3bb..f574b1b 100644 --- a/CUETools.Codecs.FLAKE/lpc.cs +++ b/CUETools.Codecs.FLAKE/lpc.cs @@ -29,6 +29,7 @@ namespace CUETools.Codecs.FLAKE { public const int MAX_LPC_ORDER = 32; public const int MAX_LPC_WINDOWS = 4; + public const int MAX_LPC_PRECISIONS = 4; /** * Apply Welch window function to audio block @@ -50,7 +51,7 @@ namespace CUETools.Codecs.FLAKE * A Welch window function is applied before calculation. */ static public unsafe void - compute_autocorr(/*const*/ int* data, uint len, uint lag, double* autoc, double* window) + compute_autocorr(/*const*/ int* data, uint len, uint min, uint lag, double* autoc, double* window) { double* data1 = stackalloc double[(int)len + 16]; uint i, j; @@ -65,7 +66,7 @@ namespace CUETools.Codecs.FLAKE } data1[len] = 0; - for (i = 0; i <= lag; ++i) + for (i = min; i <= lag; ++i) { temp = 1.0; temp2 = 1.0; @@ -289,10 +290,10 @@ namespace CUETools.Codecs.FLAKE { double* autoc = stackalloc double[MAX_LPC_ORDER + 1]; - compute_autocorr(samples, blocksize, max_order + 1, autoc, window); + compute_autocorr(samples, blocksize, 0, max_order, autoc, window); uint opt_order = max_order; - if (omethod == OrderMethod.Estimate || omethod == OrderMethod.EstSearch) + if (omethod == OrderMethod.Estimate) opt_order = compute_lpc_coefs_est(autoc, max_order, lpcs); else compute_lpc_coefs(autoc, max_order, null, lpcs); diff --git a/CUETools.Flake/Program.cs b/CUETools.Flake/Program.cs index e635f40..30b8081 100644 --- a/CUETools.Flake/Program.cs +++ b/CUETools.Flake/Program.cs @@ -34,6 +34,7 @@ namespace CUETools.FlakeExe Console.WriteLine("LPC options:"); Console.WriteLine(); Console.WriteLine(" -m Prediction order search (estimate,estsearch,logfast,search)."); + Console.WriteLine(" -e # Estimation depth (1..32)."); Console.WriteLine(" -w [,] One or more window functions (welch,hann,flattop,tukey)."); Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32)."); Console.WriteLine(" --max-precision Coefficients precision search (0..1)."); @@ -60,7 +61,8 @@ namespace CUETools.FlakeExe 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, - max_precision = -1, blocksize = -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; @@ -78,7 +80,7 @@ namespace CUETools.FlakeExe else if (args[arg] == "--no-seektable") do_seektable = false; else if (args[arg] == "--no-md5") - do_seektable = false; + do_md5 = false; 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) @@ -110,8 +112,15 @@ namespace CUETools.FlakeExe int.TryParse(args[arg].Split(',')[1], out max_fixed_order)) || int.TryParse(args[arg], out max_fixed_order); } - else if (args[arg] == "--max-precision" && ++arg < args.Length) - ok = int.TryParse(args[arg], out max_precision); + 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) @@ -192,8 +201,12 @@ namespace CUETools.FlakeExe 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.PaddingLength = padding; if (vbr_mode >= 0) @@ -252,12 +265,12 @@ namespace CUETools.FlakeExe 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}\t{13}\t{14}", + 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, flake.PredictionType.ToString().PadRight(15), flake.StereoMethod.ToString().PadRight(15), - flake.OrderMethod.ToString().PadRight(15), + (flake.OrderMethod.ToString() + (flake.OrderMethod == OrderMethod.Estimate ? "(" + flake.EstimationDepth.ToString() + ")" : "")).PadRight(15), flake.WindowFunction, flake.MinPartitionOrder, flake.MaxPartitionOrder, @@ -265,6 +278,7 @@ namespace CUETools.FlakeExe flake.MaxLPCOrder, flake.MinFixedOrder, flake.MaxFixedOrder, + flake.MinPrecisionSearch, flake.MaxPrecisionSearch, flake.BlockSize, flake.VBRMode diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index 9d942ac..508ec66 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -682,7 +682,8 @@ Global {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Win32.ActiveCfg = Debug|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x64.ActiveCfg = Debug|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x86.ActiveCfg = Debug|Any CPU + {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x86.ActiveCfg = Debug|x86 + {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x86.Build.0 = Debug|x86 {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Any CPU.Build.0 = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -690,7 +691,8 @@ Global {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Win32.ActiveCfg = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x64.ActiveCfg = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x64.Build.0 = Release|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x86.ActiveCfg = Release|Any CPU + {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x86.ActiveCfg = Release|x86 + {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MAC_SDK/Source/MACLib/Assembly/Assembly.obj b/MAC_SDK/Source/MACLib/Assembly/Assembly.obj index 87dfb95..123adbe 100644 Binary files a/MAC_SDK/Source/MACLib/Assembly/Assembly.obj and b/MAC_SDK/Source/MACLib/Assembly/Assembly.obj differ