flake optimized

This commit is contained in:
chudov
2009-08-26 17:30:17 +00:00
parent c1c83e9e5f
commit 108c9c328c
6 changed files with 203 additions and 136 deletions

View File

@@ -149,10 +149,11 @@ namespace CUETools.Codecs.FLAKE
public uint obits; public uint obits;
public uint wbits; public uint wbits;
public int* samples; 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 uint done_fixed;
public fixed double lpcs_reff[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_WINDOWS]; public fixed double reflection_coeffs[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_WINDOWS];
public fixed int lpcs_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 unsafe struct FlacFrame
@@ -174,8 +175,7 @@ namespace CUETools.Codecs.FLAKE
Estimate = 1, Estimate = 1,
LogFast = 2, LogFast = 2,
LogSearch = 3, LogSearch = 3,
EstSearch = 4, EstSearch2 = 4,
Estimate8 = 6,
Search = 5 Search = 5
} }

View File

@@ -255,14 +255,25 @@ namespace CUETools.Codecs.FLAKE
set { eparams.stereo_method = value; } 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 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"); 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 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()); throw new Exception("invalid MaxLPCOrder " + value.ToString());
eparams.max_prediction_order = value; 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 public int MinFixedOrder
{ {
get get
@@ -559,11 +584,11 @@ namespace CUETools.Codecs.FLAKE
frame->subframes[ch].best.residual = r; frame->subframes[ch].best.residual = r;
frame->subframes[ch].best.type = SubframeType.Verbatim; frame->subframes[ch].best.type = SubframeType.Verbatim;
frame->subframes[ch].best.size = UINT32_MAX; 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_lpcs[iWindow] = 0;
frame->subframes[ch].done_fixed = 0; frame->subframes[ch].done_fixed = 0;
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++) 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) 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 if (frame->blocksize <= 16384) lpc_precision = 14U;
else lpc_precision = 15; 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 // 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)); 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.type = SubframeType.LPC;
frame->current.order = order; frame->current.order = order;
@@ -819,10 +844,32 @@ namespace CUETools.Codecs.FLAKE
choose_best_subframe(frame, ch); 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* smp = frame->subframes[ch].samples;
int i, n = frame->blocksize; 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 // CONSTANT
for (i = 1; i < n; i++) for (i = 1; i < n; i++)
@@ -847,8 +894,9 @@ namespace CUETools.Codecs.FLAKE
// FIXED // FIXED
if (predict == PredictionType.Fixed || if (predict == PredictionType.Fixed ||
predict == PredictionType.Search || (predict == PredictionType.Search && pass != 1) ||
(predict == PredictionType.Estimated && frame->subframes[ch].best.type == SubframeType.Fixed) || //predict == PredictionType.Search ||
//(pass == 2 && frame->subframes[ch].best.type == SubframeType.Fixed) ||
n <= eparams.max_prediction_order) n <= eparams.max_prediction_order)
{ {
int max_fixed_order = Math.Min(eparams.max_fixed_order, 4); int max_fixed_order = Math.Min(eparams.max_fixed_order, 4);
@@ -861,8 +909,10 @@ namespace CUETools.Codecs.FLAKE
// LPC // LPC
if (n > eparams.max_prediction_order && if (n > eparams.max_prediction_order &&
(predict == PredictionType.Levinson || (predict == PredictionType.Levinson ||
predict == PredictionType.Search || predict == PredictionType.Search)
(predict == PredictionType.Estimated && frame->subframes[ch].best.type == SubframeType.LPC))) //predict == PredictionType.Search ||
//(pass == 2 && frame->subframes[ch].best.type == SubframeType.LPC))
)
{ {
//double* lpcs = stackalloc double[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER]; //double* lpcs = stackalloc double[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER];
int min_order = eparams.min_prediction_order; int min_order = eparams.min_prediction_order;
@@ -870,41 +920,12 @@ namespace CUETools.Codecs.FLAKE
for (int iWindow = 0; iWindow < _windowcount; iWindow++) for (int iWindow = 0; iWindow < _windowcount; iWindow++)
{ {
if (predict == PredictionType.Estimated && frame->subframes[ch].best.window != iWindow) if (pass == 2 && iWindow != best_window)
continue; continue;
double* reff = frame->subframes[ch].lpcs_reff + iWindow * lpc.MAX_LPC_ORDER; double* reff = get_reflection_coeffs(frame, ch, max_order, iWindow);
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* lpcs = stackalloc double[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER]; 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) switch (omethod)
{ {
@@ -913,23 +934,33 @@ namespace CUETools.Codecs.FLAKE
encode_residual_lpc_sub(frame, lpcs, iWindow, max_order, ch); encode_residual_lpc_sub(frame, lpcs, iWindow, max_order, ch);
break; break;
case OrderMethod.Estimate: case OrderMethod.Estimate:
// estimated order // estimated orders
encode_residual_lpc_sub(frame, lpcs, iWindow, est_order, ch); // 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; break;
case OrderMethod.Estimate8: case OrderMethod.EstSearch2:
// estimated order // Search at reflection coeff thresholds (where they cross 0.10)
encode_residual_lpc_sub(frame, lpcs, iWindow, est_order2, ch); {
break; int found = 0;
//case OrderMethod.EstSearch: for (i = min_order; i <= max_order && found < eparams.estimation_depth; i++)
// brute-force search starting from estimate if (is_interesting_order(reff, i, max_order))
//encode_residual_lpc_sub(frame, lpcs, iWindow, est_order, ch); {
//encode_residual_lpc_sub(frame, lpcs, iWindow, est_order2, ch); encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch);
//break; found++;
case OrderMethod.EstSearch: }
// brute-force search starting from estimate if (0 == found)
for (i = est_order; i >= min_order; i--) encode_residual_lpc_sub(frame, lpcs, iWindow, min_order, ch);
if (i == est_order || Math.Abs(reff[i - 1]) > 0.10) }
encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch);
break; break;
case OrderMethod.Search: case OrderMethod.Search:
// brute-force optimal order search // brute-force optimal order search
@@ -939,7 +970,6 @@ namespace CUETools.Codecs.FLAKE
case OrderMethod.LogFast: case OrderMethod.LogFast:
// Try max, est, 32,16,8,4,2,1 // 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, iWindow, max_order, ch);
//encode_residual_lpc_sub(frame, lpcs, est_order, ch);
for (i = lpc.MAX_LPC_ORDER; i >= min_order; i >>= 1) for (i = lpc.MAX_LPC_ORDER; i >= min_order; i >>= 1)
if (i < max_order) if (i < max_order)
encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch);
@@ -947,7 +977,6 @@ namespace CUETools.Codecs.FLAKE
case OrderMethod.LogSearch: case OrderMethod.LogSearch:
// do LogFast first // do LogFast first
encode_residual_lpc_sub(frame, lpcs, iWindow, max_order, ch); 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) for (i = lpc.MAX_LPC_ORDER; i >= min_order; i >>= 1)
if (i < max_order) if (i < max_order)
encode_residual_lpc_sub(frame, lpcs, iWindow, i, ch); 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) 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, frame->bs_code0);
bitwriter.writebits(4, sr_code0); bitwriter.writebits(4, sr_code0);
if (frame->ch_mode == ChannelMode.NotStereo) 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); 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) unsafe void estimate_frame(FlacFrame* frame, bool do_midside)
{ {
int subframes = do_midside ? channels * 2 : channels; 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); frame->subframes[ch].best.size = (uint)frame->blocksize * 32 + calc_decorr_score(frame, ch);
break; break;
case StereoMethod.Evaluate: case StereoMethod.Evaluate:
for (int ch = 0; ch < subframes; ch++)
{ {
int max_prediction_order = eparams.max_prediction_order; int windowcount = _windowcount;
int max_fixed_order = eparams.max_fixed_order; _windowcount = 1;
int min_fixed_order = eparams.min_fixed_order; encode_residual_pass1(frame, ch);
int lpc_precision_search = eparams.lpc_precision_search; _windowcount = windowcount;
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;
} }
break;
case StereoMethod.Search: case StereoMethod.Search:
for (int ch = 0; ch < subframes; ch++) for (int ch = 0; ch < subframes; ch++)
encode_residual(frame, ch, eparams.prediction_type, eparams.order_method); encode_residual_onepass(frame, ch);
break; break;
} }
} }
@@ -1278,12 +1332,16 @@ namespace CUETools.Codecs.FLAKE
for (int ch = 0; ch < channels; ch++) for (int ch = 0; ch < channels; ch++)
{ {
frame->subframes[ch].best.size = UINT32_MAX; frame->subframes[ch].best.size = UINT32_MAX;
encode_residual(frame, ch, eparams.prediction_type, eparams.order_method); encode_residual_onepass(frame, ch);
} }
break; break;
case StereoMethod.Evaluate: case StereoMethod.Evaluate:
for (int ch = 0; ch < channels; ch++) 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; break;
case StereoMethod.Search: case StereoMethod.Search:
break; break;
@@ -1343,7 +1401,7 @@ namespace CUETools.Codecs.FLAKE
bits_per_sample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); bits_per_sample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));
for (int ch = 0; ch < channels; ch++) for (int ch = 0; ch < channels; ch++)
encode_residual(&frame, ch, eparams.prediction_type, eparams.order_method); encode_residual_onepass(&frame, ch);
} }
else else
{ {
@@ -1819,6 +1877,12 @@ namespace CUETools.Codecs.FLAKE
// valid values are 1 to 32 // valid values are 1 to 32
public int max_prediction_order; 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 // minimum fixed prediction order
// set by user prior to calling flake_encode_init // set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression. // 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 // whether to try various lpc_precisions
// 0 - use only one precision // 0 - use only one precision
// 1 - try two precisions // 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; public WindowFunction window_function;
@@ -1882,12 +1948,14 @@ namespace CUETools.Codecs.FLAKE
prediction_type = PredictionType.Search; prediction_type = PredictionType.Search;
min_prediction_order = 1; min_prediction_order = 1;
max_prediction_order = 8; max_prediction_order = 8;
estimation_depth = 1;
min_fixed_order = 2; min_fixed_order = 2;
max_fixed_order = 2; max_fixed_order = 2;
min_partition_order = 0; min_partition_order = 0;
max_partition_order = 6; max_partition_order = 6;
variable_block_size = 0; variable_block_size = 0;
lpc_precision_search = 0; lpc_min_precision_search = 1;
lpc_max_precision_search = 1;
do_md5 = true; do_md5 = true;
do_verify = false; do_verify = false;
do_seektable = true; do_seektable = true;
@@ -1907,55 +1975,37 @@ namespace CUETools.Codecs.FLAKE
max_partition_order = 4; max_partition_order = 4;
break; break;
case 2: case 2:
prediction_type = PredictionType.Search;
stereo_method = StereoMethod.Independent; stereo_method = StereoMethod.Independent;
window_function = WindowFunction.Welch; window_function = WindowFunction.Welch;
max_prediction_order = 12; max_prediction_order = 12;
max_partition_order = 4; max_partition_order = 4;
break; break;
case 3: case 3:
prediction_type = PredictionType.Levinson; stereo_method = StereoMethod.Estimate;
stereo_method = StereoMethod.Evaluate;
window_function = WindowFunction.Welch; window_function = WindowFunction.Welch;
max_partition_order = 4;
break; break;
case 4: case 4:
prediction_type = PredictionType.Levinson; stereo_method = StereoMethod.Estimate;
stereo_method = StereoMethod.Evaluate;
window_function = WindowFunction.Welch; window_function = WindowFunction.Welch;
max_prediction_order = 12; max_prediction_order = 12;
max_partition_order = 4;
break; break;
case 5: case 5:
prediction_type = PredictionType.Search;
stereo_method = StereoMethod.Evaluate;
window_function = WindowFunction.Welch; window_function = WindowFunction.Welch;
max_prediction_order = 12; max_prediction_order = 12;
break; break;
case 6: case 6:
prediction_type = PredictionType.Levinson; stereo_method = StereoMethod.Estimate;
stereo_method = StereoMethod.Evaluate;
window_function = WindowFunction.Flattop | WindowFunction.Tukey;
max_prediction_order = 12; max_prediction_order = 12;
break; break;
case 7: case 7:
prediction_type = PredictionType.Search;
stereo_method = StereoMethod.Evaluate;
window_function = WindowFunction.Flattop | WindowFunction.Tukey;
max_prediction_order = 12; max_prediction_order = 12;
min_fixed_order = 0;
max_fixed_order = 4;
lpc_precision_search = 1;
break; break;
case 8: case 8:
prediction_type = PredictionType.Search; estimation_depth = 3;
stereo_method = StereoMethod.Evaluate;
window_function = WindowFunction.Flattop | WindowFunction.Tukey;
order_method = OrderMethod.EstSearch;
max_prediction_order = 12; max_prediction_order = 12;
min_fixed_order = 0; min_fixed_order = 0;
max_fixed_order = 4; max_fixed_order = 4;
lpc_precision_search = 1; lpc_max_precision_search = 2;
break; break;
case 9: case 9:
window_function = WindowFunction.Welch; window_function = WindowFunction.Welch;
@@ -1965,14 +2015,14 @@ namespace CUETools.Codecs.FLAKE
min_fixed_order = 0; min_fixed_order = 0;
max_fixed_order = 4; max_fixed_order = 4;
max_prediction_order = 32; max_prediction_order = 32;
lpc_precision_search = 0; //lpc_max_precision_search = 2;
break; break;
case 11: case 11:
order_method = OrderMethod.EstSearch;
min_fixed_order = 0; min_fixed_order = 0;
max_fixed_order = 4; max_fixed_order = 4;
max_prediction_order = 32; max_prediction_order = 32;
//lpc_precision_search = 1; estimation_depth = 5;
//lpc_max_precision_search = 2;
variable_block_size = 4; variable_block_size = 4;
break; break;
} }

View File

@@ -29,6 +29,7 @@ namespace CUETools.Codecs.FLAKE
{ {
public const int MAX_LPC_ORDER = 32; public const int MAX_LPC_ORDER = 32;
public const int MAX_LPC_WINDOWS = 4; public const int MAX_LPC_WINDOWS = 4;
public const int MAX_LPC_PRECISIONS = 4;
/** /**
* Apply Welch window function to audio block * Apply Welch window function to audio block
@@ -50,7 +51,7 @@ namespace CUETools.Codecs.FLAKE
* A Welch window function is applied before calculation. * A Welch window function is applied before calculation.
*/ */
static public unsafe void 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]; double* data1 = stackalloc double[(int)len + 16];
uint i, j; uint i, j;
@@ -65,7 +66,7 @@ namespace CUETools.Codecs.FLAKE
} }
data1[len] = 0; data1[len] = 0;
for (i = 0; i <= lag; ++i) for (i = min; i <= lag; ++i)
{ {
temp = 1.0; temp = 1.0;
temp2 = 1.0; temp2 = 1.0;
@@ -289,10 +290,10 @@ namespace CUETools.Codecs.FLAKE
{ {
double* autoc = stackalloc double[MAX_LPC_ORDER + 1]; 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; 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); opt_order = compute_lpc_coefs_est(autoc, max_order, lpcs);
else else
compute_lpc_coefs(autoc, max_order, null, lpcs); compute_lpc_coefs(autoc, max_order, null, lpcs);

View File

@@ -34,6 +34,7 @@ namespace CUETools.FlakeExe
Console.WriteLine("LPC options:"); Console.WriteLine("LPC options:");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(" -m <method> Prediction order search (estimate,estsearch,logfast,search)."); Console.WriteLine(" -m <method> Prediction order search (estimate,estsearch,logfast,search).");
Console.WriteLine(" -e # Estimation depth (1..32).");
Console.WriteLine(" -w <func>[,<func>] One or more window functions (welch,hann,flattop,tukey)."); Console.WriteLine(" -w <func>[,<func>] One or more window functions (welch,hann,flattop,tukey).");
Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32)."); Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32).");
Console.WriteLine(" --max-precision Coefficients precision search (0..1)."); 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, int min_partition_order = -1, max_partition_order = -1,
min_lpc_order = -1, max_lpc_order = -1, min_lpc_order = -1, max_lpc_order = -1,
min_fixed_order = -1, max_fixed_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; int level = -1, padding = -1, vbr_mode = -1;
bool do_md5 = true, do_seektable = true, do_verify = false; bool do_md5 = true, do_seektable = true, do_verify = false;
@@ -78,7 +80,7 @@ namespace CUETools.FlakeExe
else if (args[arg] == "--no-seektable") else if (args[arg] == "--no-seektable")
do_seektable = false; do_seektable = false;
else if (args[arg] == "--no-md5") else if (args[arg] == "--no-md5")
do_seektable = false; do_md5 = false;
else if ((args[arg] == "-o" || args[arg] == "--output") && ++arg < args.Length) else if ((args[arg] == "-o" || args[arg] == "--output") && ++arg < args.Length)
output_file = args[arg]; output_file = args[arg];
else if ((args[arg] == "-t" || args[arg] == "--prediction-type") && ++arg < args.Length) 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].Split(',')[1], out max_fixed_order)) ||
int.TryParse(args[arg], out max_fixed_order); int.TryParse(args[arg], out max_fixed_order);
} }
else if (args[arg] == "--max-precision" && ++arg < args.Length) else if ((args[arg] == "-e" || args[arg] == "--estimation-depth") && ++arg < args.Length)
ok = int.TryParse(args[arg], out max_precision); 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")) else if ((args[arg] == "-v" || args[arg] == "--vbr"))
ok = (++arg < args.Length) && int.TryParse(args[arg], out vbr_mode); ok = (++arg < args.Length) && int.TryParse(args[arg], out vbr_mode);
else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length) else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length)
@@ -192,8 +201,12 @@ namespace CUETools.FlakeExe
flake.MaxFixedOrder = max_fixed_order; flake.MaxFixedOrder = max_fixed_order;
if (max_precision >= 0) if (max_precision >= 0)
flake.MaxPrecisionSearch = max_precision; flake.MaxPrecisionSearch = max_precision;
if (min_precision >= 0)
flake.MinPrecisionSearch = min_precision;
if (blocksize >= 0) if (blocksize >= 0)
flake.BlockSize = blocksize; flake.BlockSize = blocksize;
if (estimation_depth >= 0)
flake.EstimationDepth = estimation_depth;
if (padding >= 0) if (padding >= 0)
flake.PaddingLength = padding; flake.PaddingLength = padding;
if (vbr_mode >= 0) if (vbr_mode >= 0)
@@ -252,12 +265,12 @@ namespace CUETools.FlakeExe
if (debug) if (debug)
{ {
Console.SetOut(stdout); 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.TotalSize,
flake.UserProcessorTime.TotalSeconds, flake.UserProcessorTime.TotalSeconds,
flake.PredictionType.ToString().PadRight(15), flake.PredictionType.ToString().PadRight(15),
flake.StereoMethod.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.WindowFunction,
flake.MinPartitionOrder, flake.MinPartitionOrder,
flake.MaxPartitionOrder, flake.MaxPartitionOrder,
@@ -265,6 +278,7 @@ namespace CUETools.FlakeExe
flake.MaxLPCOrder, flake.MaxLPCOrder,
flake.MinFixedOrder, flake.MinFixedOrder,
flake.MaxFixedOrder, flake.MaxFixedOrder,
flake.MinPrecisionSearch,
flake.MaxPrecisionSearch, flake.MaxPrecisionSearch,
flake.BlockSize, flake.BlockSize,
flake.VBRMode flake.VBRMode

View File

@@ -682,7 +682,8 @@ Global
{2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {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|Win32.ActiveCfg = Debug|Any CPU
{2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x64.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.ActiveCfg = Release|Any CPU
{2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Any CPU.Build.0 = 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 {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|Win32.ActiveCfg = Release|Any CPU
{2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x64.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|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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE