Simplify codec settings. Check for non-Subset FLAC modes.

This commit is contained in:
Grigory Chudov
2013-06-18 20:45:53 -04:00
parent 21a1628018
commit bcb42dd531
10 changed files with 413 additions and 546 deletions

View File

@@ -187,7 +187,6 @@ namespace CUETools.ALACEnc
try try
{ {
settings.Validate();
if (stereo_method != null) if (stereo_method != null)
alac.StereoMethod = Alac.LookupStereoMethod(stereo_method); alac.StereoMethod = Alac.LookupStereoMethod(stereo_method);
if (order_method != null) if (order_method != null)

View File

@@ -40,10 +40,12 @@ namespace CUETools.Codecs.ALAC
{ {
} }
public override bool IsValid() public void Validate()
{ {
return EncoderModeIndex >= 0 && Padding >= 0 && if (EncoderModeIndex < 0
(BlockSize == 0 || BlockSize >= 256 && BlockSize < Int32.MaxValue); || Padding < 0
|| (BlockSize != 0 && (BlockSize < 256 || BlockSize >= Int32.MaxValue)))
throw new Exception("unsupported encoder settings");
} }
[DefaultValue(false)] [DefaultValue(false)]
@@ -105,6 +107,7 @@ namespace CUETools.Codecs.ALAC
public ALACWriter(string path, Stream IO, ALACWriterSettings settings) public ALACWriter(string path, Stream IO, ALACWriterSettings settings)
{ {
m_settings = settings; m_settings = settings;
m_settings.Validate();
if (Settings.PCM.BitsPerSample != 16) if (Settings.PCM.BitsPerSample != 16)
throw new Exception("Bits per sample must be 16."); throw new Exception("Bits per sample must be 16.");
@@ -1216,8 +1219,6 @@ namespace CUETools.Codecs.ALAC
_IO = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); _IO = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
if (_IO != null && !_IO.CanSeek) if (_IO != null && !_IO.CanSeek)
throw new NotSupportedException("stream doesn't support seeking"); throw new NotSupportedException("stream doesn't support seeking");
if (!m_settings.IsValid())
throw new Exception("unsupported encoder settings");
encode_init(); encode_init();
inited = true; inited = true;
} }

View File

@@ -41,16 +41,127 @@ namespace CUETools.Codecs.FLACCL
public override string GetSupportedModes(out string defaultMode) public override string GetSupportedModes(out string defaultMode)
{ {
defaultMode = "8"; defaultMode = "8";
return this.AllowNonSubset ? "0 1 2 3 4 5 6 7 8 9 10 11" : "0 1 2 3 4 5 6 7 8"; return this.AllowNonSubset || (this.PCM != null && this.PCM.SampleRate > 48000) ? "0 1 2 3 4 5 6 7 8 9 10 11" : "0 1 2 3 4 5 6 7 8";
} }
public override bool IsValid() public bool IsSubset()
{ {
return EncoderModeIndex >= 0 && Padding >= 0 && return (BlockSize == 0 || (BlockSize <= 16384 && (PCM.SampleRate > 48000 || BlockSize <= 4608)))
(BlockSize == 0 || (BlockSize >= 256 && BlockSize <= Flake.MAX_BLOCKSIZE)) && && (PCM.SampleRate > 48000 || MaxLPCOrder <= 12)
(AllowNonSubset || EncoderModeIndex <= 8); && MaxPartitionOrder <= 8
;
//The blocksize bits in the frame header must be 0001-1110. The blocksize must be <=16384; if the sample rate is <= 48000Hz, the blocksize must be <=4608.
//The sample rate bits in the frame header must be 0001-1110.
//The bits-per-sample bits in the frame header must be 001-111.
//If the sample rate is <= 48000Hz, the filter order in LPC subframes must be less than or equal to 12, i.e. the subframe type bits in the subframe header may not be 101100-111111.
//The Rice partition order in a Rice-coded residual section must be less than or equal to 8.
} }
public void Validate()
{
if (EncoderModeIndex < 0)
throw new Exception("unsupported encoder mode");
var thisModeSettings = FLACCLWriterSettings.modeSettings[EncoderModeIndex];
if (MaxLPCOrder < 0)
MaxLPCOrder = thisModeSettings.MaxLPCOrder;
if (MinFixedOrder < 0)
MinFixedOrder = thisModeSettings.MinFixedOrder;
if (MaxFixedOrder < 0)
MaxFixedOrder = thisModeSettings.MaxFixedOrder;
if (Padding < 0)
throw new Exception("unsupported padding value " + Padding.ToString());
if (BlockSize != 0 && (BlockSize < 256 || BlockSize >= Flake.MAX_BLOCKSIZE))
throw new Exception("unsupported block size " + BlockSize.ToString());
if (MinLPCOrder > MaxLPCOrder || MaxLPCOrder > lpc.MAX_LPC_ORDER)
throw new Exception("invalid MaxLPCOrder " + MaxLPCOrder.ToString());
if (MinFixedOrder < 0 || MinFixedOrder > 4)
throw new Exception("invalid MinFixedOrder " + MinFixedOrder.ToString());
if (MaxFixedOrder < 0 || MaxFixedOrder > 4)
throw new Exception("invalid MaxFixedOrder " + MaxFixedOrder.ToString());
if (MinPartitionOrder < 0)
throw new Exception("invalid MinPartitionOrder " + MinPartitionOrder.ToString());
if (MinPartitionOrder > MaxPartitionOrder || MaxPartitionOrder > 8)
throw new Exception("invalid MaxPartitionOrder " + MaxPartitionOrder.ToString());
if (!AllowNonSubset && !IsSubset())
throw new Exception("the encoding parameters specified do not conform to the FLAC Subset");
}
private static FLACCLWriterSettings[] modeSettings =
{
new FLACCLWriterSettings() {
MinFixedOrder = 3, MaxFixedOrder = 2, MaxLPCOrder = 7,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 7,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 8,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 8,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 8,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 8,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12,
},
new FLACCLWriterSettings() {
MinFixedOrder = 0, MaxFixedOrder = 4, MaxLPCOrder = 12,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 32,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 32,
},
new FLACCLWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 32,
},
};
[DefaultValue(-1)]
[Browsable(false)]
[DisplayName("MinFixedOrder")]
[SRDescription(typeof(Properties.Resources), "MinFixedOrderDescription")]
public int MinFixedOrder { get; set; }
[DefaultValue(-1)]
[Browsable(false)]
[DisplayName("MaxFixedOrder")]
[SRDescription(typeof(Properties.Resources), "MaxFixedOrderDescription")]
public int MaxFixedOrder { get; set; }
[DefaultValue(1)]
[Browsable(false)]
[DisplayName("MinLPCOrder")]
[SRDescription(typeof(Properties.Resources), "MinLPCOrderDescription")]
public int MinLPCOrder { get; set; }
[DefaultValue(-1)]
[Browsable(false)]
[DisplayName("MaxLPCOrder")]
[SRDescription(typeof(Properties.Resources), "MaxLPCOrderDescription")]
public int MaxLPCOrder { get; set; }
[DefaultValue(0)]
[DisplayName("MinPartitionOrder")]
[Browsable(false)]
[SRDescription(typeof(Properties.Resources), "MinPartitionOrderDescription")]
public int MinPartitionOrder { get; set; }
[DefaultValue(8)]
[DisplayName("MaxPartitionOrder")]
[Browsable(false)]
[SRDescription(typeof(Properties.Resources), "MaxPartitionOrderDescription")]
public int MaxPartitionOrder { get; set; }
[DefaultValue(false)] [DefaultValue(false)]
[DisplayName("Verify")] [DisplayName("Verify")]
[SRDescription(typeof(Properties.Resources), "DoVerifyDescription")] [SRDescription(typeof(Properties.Resources), "DoVerifyDescription")]
@@ -70,6 +181,7 @@ namespace CUETools.Codecs.FLACCL
public bool DoRice { get; set; } public bool DoRice { get; set; }
[DefaultValue(false)] [DefaultValue(false)]
[Browsable(false)]
[SRDescription(typeof(Properties.Resources), "DescriptionMappedMemory")] [SRDescription(typeof(Properties.Resources), "DescriptionMappedMemory")]
public bool MappedMemory { get; set; } public bool MappedMemory { get; set; }
@@ -79,10 +191,12 @@ namespace CUETools.Codecs.FLACCL
public int GroupSize { get; set; } public int GroupSize { get; set; }
[DefaultValue(8)] [DefaultValue(8)]
[Browsable(false)]
[SRDescription(typeof(Properties.Resources), "DescriptionTaskSize")] [SRDescription(typeof(Properties.Resources), "DescriptionTaskSize")]
public int TaskSize { get; set; } public int TaskSize { get; set; }
[SRDescription(typeof(Properties.Resources), "DescriptionDefines")] [SRDescription(typeof(Properties.Resources), "DescriptionDefines")]
[Browsable(false)]
public string Defines { get; set; } public string Defines { get; set; }
[TypeConverter(typeof(FLACCLWriterSettingsPlatformConverter))] [TypeConverter(typeof(FLACCLWriterSettingsPlatformConverter))]
@@ -164,7 +278,7 @@ namespace CUETools.Codecs.FLACCL
int channels, ch_code; int channels, ch_code;
// audio sample rate in Hz // audio sample rate in Hz
int sample_rate, sr_code0, sr_code1; int sr_code0, sr_code1;
// sample size in bits // sample size in bits
// only 16-bit is currently supported // only 16-bit is currently supported
@@ -219,7 +333,8 @@ namespace CUETools.Codecs.FLACCL
public FLACCLWriter(string path, Stream IO, FLACCLWriterSettings settings) public FLACCLWriter(string path, Stream IO, FLACCLWriterSettings settings)
{ {
m_settings = settings; m_settings = settings.Clone() as FLACCLWriterSettings;
m_settings.Validate();
// FIXME: For now, only 16-bit encoding is supported // FIXME: For now, only 16-bit encoding is supported
if (Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24) if (Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24)
@@ -228,7 +343,6 @@ namespace CUETools.Codecs.FLACCL
// throw new Exception("ChannelCount must be 2."); // throw new Exception("ChannelCount must be 2.");
channels = Settings.PCM.ChannelCount; channels = Settings.PCM.ChannelCount;
sample_rate = Settings.PCM.SampleRate;
bits_per_sample = (uint)Settings.PCM.BitsPerSample; bits_per_sample = (uint)Settings.PCM.BitsPerSample;
// flake_validate_params // flake_validate_params
@@ -236,8 +350,7 @@ namespace CUETools.Codecs.FLACCL
_path = path; _path = path;
_IO = IO; _IO = IO;
var _compressionLevel = Settings.EncoderModeIndex; eparams.flake_set_defaults(m_settings);
eparams.flake_set_defaults(_compressionLevel);
crc8 = new Crc8(); crc8 = new Crc8();
} }
@@ -468,62 +581,6 @@ namespace CUETools.Codecs.FLACCL
} }
} }
public int MinLPCOrder
{
get
{
return eparams.min_prediction_order;
}
set
{
if (value < 1 || value > eparams.max_prediction_order)
throw new Exception("invalid MinLPCOrder " + value.ToString());
eparams.min_prediction_order = value;
}
}
public int MaxLPCOrder
{
get
{
return eparams.max_prediction_order;
}
set
{
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 MinFixedOrder
{
get
{
return eparams.min_fixed_order;
}
set
{
if (value < 0 || value > 4)
throw new Exception("invalid MinFixedOrder " + value.ToString());
eparams.min_fixed_order = value;
}
}
public int MaxFixedOrder
{
get
{
return eparams.max_fixed_order;
}
set
{
if (value > 4 || value < 0)
throw new Exception("invalid MaxFixedOrder " + value.ToString());
eparams.max_fixed_order = value;
}
}
public bool DoConstant public bool DoConstant
{ {
get { return eparams.do_constant; } get { return eparams.do_constant; }
@@ -536,28 +593,6 @@ namespace CUETools.Codecs.FLACCL
set { eparams.estimate_window = value; } set { eparams.estimate_window = value; }
} }
public int MinPartitionOrder
{
get { return eparams.min_partition_order; }
set
{
if (value < 0 || value > eparams.max_partition_order)
throw new Exception("invalid MinPartitionOrder " + value.ToString());
eparams.min_partition_order = value;
}
}
public int MaxPartitionOrder
{
get { return eparams.max_partition_order; }
set
{
if (value > 8 || value < eparams.min_partition_order)
throw new Exception("invalid MaxPartitionOrder " + value.ToString());
eparams.max_partition_order = value;
}
}
public TimeSpan UserProcessorTime public TimeSpan UserProcessorTime
{ {
get { return _userProcessorTime; } get { return _userProcessorTime; }
@@ -1095,7 +1130,7 @@ namespace CUETools.Codecs.FLACCL
task.nResidualTasks = 0; task.nResidualTasks = 0;
task.nTasksPerWindow = Math.Min(32, eparams.orders_per_window); task.nTasksPerWindow = Math.Min(32, eparams.orders_per_window);
task.nResidualTasksPerChannel = task.nWindowFunctions * task.nTasksPerWindow + (eparams.do_constant ? 1 : 0) + Math.Max(0, 1 + eparams.max_fixed_order - eparams.min_fixed_order); task.nResidualTasksPerChannel = task.nWindowFunctions * task.nTasksPerWindow + (eparams.do_constant ? 1 : 0) + Math.Max(0, 1 + m_settings.MaxFixedOrder - m_settings.MinFixedOrder);
if (task.nResidualTasksPerChannel > 32) if (task.nResidualTasksPerChannel > 32)
throw new Exception("too many tasks"); throw new Exception("too many tasks");
if (channels == 2 && channelsCount == 4) if (channels == 2 && channelsCount == 4)
@@ -1160,7 +1195,7 @@ namespace CUETools.Codecs.FLACCL
task.nResidualTasks++; task.nResidualTasks++;
} }
// Fixed prediction // Fixed prediction
for (int order = eparams.min_fixed_order; order <= eparams.max_fixed_order; order++) for (int order = m_settings.MinFixedOrder; order <= m_settings.MaxFixedOrder; order++)
{ {
task.ResidualTasks[task.nResidualTasks].type = (int)SubframeType.Fixed; task.ResidualTasks[task.nResidualTasks].type = (int)SubframeType.Fixed;
task.ResidualTasks[task.nResidualTasks].channel = ch; task.ResidualTasks[task.nResidualTasks].channel = ch;
@@ -1247,7 +1282,7 @@ namespace CUETools.Codecs.FLACCL
else else
frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight; frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight;
int toUnpack = Math.Min(task.frameSize, eparams.max_prediction_order); int toUnpack = Math.Min(task.frameSize, m_settings.MaxLPCOrder);
// calculate wbits before unpacking samples. // calculate wbits before unpacking samples.
for (int ch = 0; ch < channels; ch++) for (int ch = 0; ch < channels; ch++)
{ {
@@ -1256,7 +1291,7 @@ namespace CUETools.Codecs.FLACCL
frame.subframes[ch].best.type = SubframeType.Verbatim; frame.subframes[ch].best.type = SubframeType.Verbatim;
frame.subframes[ch].best.size = (uint)(frame.subframes[ch].obits * frame.blocksize); frame.subframes[ch].best.size = (uint)(frame.subframes[ch].obits * frame.blocksize);
frame.subframes[ch].wbits = 0; frame.subframes[ch].wbits = 0;
if (frame.blocksize > Math.Max(4, eparams.max_prediction_order)) if (frame.blocksize > Math.Max(4, m_settings.MaxLPCOrder))
{ {
if (task.BestResidualTasks[index].size < 0) if (task.BestResidualTasks[index].size < 0)
throw new Exception("internal error"); throw new Exception("internal error");
@@ -1318,8 +1353,8 @@ namespace CUETools.Codecs.FLACCL
encode_residual_fixed(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, encode_residual_fixed(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples,
task.frame.blocksize, task.frame.subframes[ch].best.order); task.frame.blocksize, task.frame.subframes[ch].best.order);
int pmin = get_max_p_order(eparams.min_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); int pmin = get_max_p_order(m_settings.MinPartitionOrder, task.frame.blocksize, task.frame.subframes[ch].best.order);
int pmax = get_max_p_order(eparams.max_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); int pmax = get_max_p_order(m_settings.MaxPartitionOrder, task.frame.blocksize, task.frame.subframes[ch].best.order);
calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, Settings.PCM.BitsPerSample > 16 ? 1 : 0); calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, Settings.PCM.BitsPerSample > 16 ? 1 : 0);
} }
break; break;
@@ -1334,8 +1369,8 @@ namespace CUETools.Codecs.FLACCL
lpc.encode_residual(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, task.frame.blocksize, task.frame.subframes[ch].best.order, coefs, task.frame.subframes[ch].best.shift); lpc.encode_residual(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, task.frame.blocksize, task.frame.subframes[ch].best.order, coefs, task.frame.subframes[ch].best.shift);
} }
int pmin = get_max_p_order(eparams.min_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); int pmin = get_max_p_order(m_settings.MinPartitionOrder, task.frame.blocksize, task.frame.subframes[ch].best.order);
int pmax = get_max_p_order(eparams.max_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); int pmax = get_max_p_order(m_settings.MaxPartitionOrder, task.frame.blocksize, task.frame.subframes[ch].best.order);
calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, Settings.PCM.BitsPerSample > 16 ? 1 : 0); calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, Settings.PCM.BitsPerSample > 16 ? 1 : 0);
} }
break; break;
@@ -1713,8 +1748,6 @@ namespace CUETools.Codecs.FLACCL
{ {
if (OpenCL.NumberOfPlatforms < 1) if (OpenCL.NumberOfPlatforms < 1)
throw new Exception("no opencl platforms found"); throw new Exception("no opencl platforms found");
if (!m_settings.IsValid())
throw new Exception("unsupported encoder settings");
int groupSize = m_settings.DeviceType == OpenCLDeviceType.CPU ? 1 : m_settings.GroupSize; int groupSize = m_settings.DeviceType == OpenCLDeviceType.CPU ? 1 : m_settings.GroupSize;
OCLMan = new OpenCLManager(); OCLMan = new OpenCLManager();
@@ -1764,14 +1797,14 @@ namespace CUETools.Codecs.FLACCL
bool UseGPURice = UseGPUOnly && m_settings.DoRice; bool UseGPURice = UseGPUOnly && m_settings.DoRice;
m_blockSize = m_settings.BlockSize != 0 ? m_settings.BlockSize : m_blockSize = m_settings.BlockSize != 0 ? m_settings.BlockSize :
select_blocksize(sample_rate, eparams.block_time_ms); select_blocksize(m_settings.PCM.SampleRate, eparams.block_time_ms);
int maxBS = 1 << (BitReader.log2i(m_blockSize - 1) + 1); int maxBS = 1 << (BitReader.log2i(m_blockSize - 1) + 1);
// The Defines string gets prepended to any and all sources that are compiled // The Defines string gets prepended to any and all sources that are compiled
// and serve as a convenient way to pass configuration information to the compilation process // and serve as a convenient way to pass configuration information to the compilation process
OCLMan.Defines = OCLMan.Defines =
"#define MAX_ORDER " + eparams.max_prediction_order.ToString() + "\n" + "#define MAX_ORDER " + m_settings.MaxLPCOrder.ToString() + "\n" +
"#define GROUP_SIZE " + groupSize.ToString() + "\n" + "#define GROUP_SIZE " + groupSize.ToString() + "\n" +
"#define GROUP_SIZE_LOG " + BitReader.log2i(groupSize).ToString() + "\n" + "#define GROUP_SIZE_LOG " + BitReader.log2i(groupSize).ToString() + "\n" +
"#define FLACCL_VERSION \"" + Vendor + "\"\n" + "#define FLACCL_VERSION \"" + Vendor + "\"\n" +
@@ -2049,7 +2082,7 @@ namespace CUETools.Codecs.FLACCL
bitwriter.writebits(16, m_blockSize); bitwriter.writebits(16, m_blockSize);
bitwriter.writebits(24, 0); bitwriter.writebits(24, 0);
bitwriter.writebits(24, max_frame_size); bitwriter.writebits(24, max_frame_size);
bitwriter.writebits(20, sample_rate); bitwriter.writebits(20, m_settings.PCM.SampleRate);
bitwriter.writebits(3, channels - 1); bitwriter.writebits(3, channels - 1);
bitwriter.writebits(5, bits_per_sample - 1); bitwriter.writebits(5, bits_per_sample - 1);
@@ -2175,7 +2208,7 @@ namespace CUETools.Codecs.FLACCL
// find samplerate in table // find samplerate in table
for (i = 1; i < 12; i++) for (i = 1; i < 12; i++)
{ {
if (sample_rate == Flake.flac_samplerates[i]) if (m_settings.PCM.SampleRate == Flake.flac_samplerates[i])
{ {
sr_code0 = i; sr_code0 = i;
break; break;
@@ -2205,7 +2238,7 @@ namespace CUETools.Codecs.FLACCL
if (_IO.CanSeek && eparams.do_seektable && sample_count > 0) if (_IO.CanSeek && eparams.do_seektable && sample_count > 0)
{ {
int seek_points_distance = sample_rate * 10; int seek_points_distance = m_settings.PCM.SampleRate * 10;
int num_seek_points = 1 + sample_count / seek_points_distance; // 1 seek point per 10 seconds int num_seek_points = 1 + sample_count / seek_points_distance; // 1 seek point per 10 seconds
if (sample_count % seek_points_distance == 0) if (sample_count % seek_points_distance == 0)
num_seek_points--; num_seek_points--;
@@ -2232,15 +2265,6 @@ namespace CUETools.Codecs.FLACCL
struct FlakeEncodeParams struct FlakeEncodeParams
{ {
// compression quality
// set by user prior to calling flake_encode_init
// standard values are 0 to 8
// 0 is lower compression, faster encoding
// 8 is higher compression, slower encoding
// extended values 9 to 12 are slower and/or use
// higher prediction orders
public int compression;
// stereo decorrelation method // stereo decorrelation method
// 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.
@@ -2255,46 +2279,10 @@ namespace CUETools.Codecs.FLACCL
// can also be changed by user before encoding a frame // can also be changed by user before encoding a frame
public int block_time_ms; public int block_time_ms;
// minimum LPC order
// 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 min_prediction_order;
// maximum LPC order
// 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 max_prediction_order;
public int orders_per_window; public int orders_per_window;
public int orders_per_channel; public int orders_per_channel;
// 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.
// valid values are 0 to 4
public int min_fixed_order;
// maximum fixed prediction order
// set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression.
// valid values are 0 to 4
public int max_fixed_order;
// minimum partition order
// set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression.
// valid values are 0 to 8
public int min_partition_order;
// maximum partition order
// set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression.
// valid values are 0 to 8
public int max_partition_order;
// whether to use variable block sizes // whether to use variable block sizes
// set by user prior to calling flake_encode_init // set by user prior to calling flake_encode_init
// 0 = fixed block size // 0 = fixed block size
@@ -2318,25 +2306,13 @@ namespace CUETools.Codecs.FLACCL
public bool do_seektable; public bool do_seektable;
public int flake_set_defaults(int lvl) public int flake_set_defaults(FLACCLWriterSettings settings)
{ {
compression = lvl; int lvl = settings.EncoderModeIndex;
if ((lvl < 0 || lvl > 12) && (lvl != 99))
{
return -1;
}
// default to level 5 params // default to level 5 params
window_function = WindowFunction.Flattop | WindowFunction.Tukey; window_function = WindowFunction.Flattop | WindowFunction.Tukey;
do_midside = true; do_midside = true;
block_time_ms = 100; block_time_ms = 100;
min_fixed_order = 0;
max_fixed_order = 4;
min_prediction_order = 1;
max_prediction_order = 12;
min_partition_order = 0;
max_partition_order = 8;
variable_block_size = 0; variable_block_size = 0;
lpc_min_precision_search = 0; lpc_min_precision_search = 0;
lpc_max_precision_search = 0; lpc_max_precision_search = 0;
@@ -2355,9 +2331,6 @@ namespace CUETools.Codecs.FLACCL
do_midside = false; do_midside = false;
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
orders_per_window = 1; orders_per_window = 1;
max_prediction_order = 7;
min_fixed_order = 3;
max_fixed_order = 2;
break; break;
case 1: case 1:
do_constant = false; do_constant = false;
@@ -2365,54 +2338,35 @@ namespace CUETools.Codecs.FLACCL
do_midside = false; do_midside = false;
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
orders_per_window = 1; orders_per_window = 1;
min_fixed_order = 2;
max_fixed_order = 2;
max_prediction_order = 7;
break; break;
case 2: case 2:
do_constant = false; do_constant = false;
do_midside = false; do_midside = false;
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
orders_per_window = 1; orders_per_window = 1;
min_fixed_order = 2;
max_fixed_order = 2;
max_prediction_order = 8;
break; break;
case 3: case 3:
do_constant = false; do_constant = false;
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 1; orders_per_window = 1;
orders_per_channel = 1; orders_per_channel = 1;
max_prediction_order = 8;
break; break;
case 4: case 4:
do_constant = false; do_constant = false;
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 2; orders_per_window = 2;
orders_per_channel = 2; orders_per_channel = 2;
max_prediction_order = 8;
break; break;
case 5: case 5:
do_constant = false; do_constant = false;
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 4; orders_per_window = 4;
orders_per_channel = 4; orders_per_channel = 4;
max_prediction_order = 8;
break; break;
case 6: case 6:
do_constant = false; do_constant = false;
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 2; orders_per_window = 2;
orders_per_channel = 2; orders_per_channel = 2;
break; break;
case 7: case 7:
do_constant = false; do_constant = false;
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 4; orders_per_window = 4;
orders_per_channel = 4; orders_per_channel = 4;
break; break;
@@ -2421,26 +2375,16 @@ namespace CUETools.Codecs.FLACCL
orders_per_channel = 8; orders_per_channel = 8;
break; break;
case 9: case 9:
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 4; orders_per_window = 4;
orders_per_channel = 4; orders_per_channel = 4;
max_prediction_order = 32;
break; break;
case 10: case 10:
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 7; orders_per_window = 7;
max_prediction_order = 32;
break; break;
case 11: case 11:
min_fixed_order = 2;
max_fixed_order = 2;
orders_per_window = 11; orders_per_window = 11;
max_prediction_order = 32;
break; break;
} }
return 0; return 0;
} }
} }
@@ -2574,7 +2518,7 @@ namespace CUETools.Codecs.FLACCL
#endif #endif
openCLCQ = openCLProgram.Context.CreateCommandQueue(openCLProgram.Context.Devices[0], prop); openCLCQ = openCLProgram.Context.CreateCommandQueue(openCLProgram.Context.Devices[0], prop);
int MAX_ORDER = this.writer.eparams.max_prediction_order; int MAX_ORDER = this.writer.m_settings.MaxLPCOrder;
int MAX_FRAMES = this.writer.framesPerTask; int MAX_FRAMES = this.writer.framesPerTask;
int MAX_CHANNELSIZE = MAX_FRAMES * ((writer.m_blockSize + 3) & ~3); int MAX_CHANNELSIZE = MAX_FRAMES * ((writer.m_blockSize + 3) & ~3);
residualTasksLen = sizeof(FLACCLSubframeTask) * 32 * channelsCount * MAX_FRAMES; residualTasksLen = sizeof(FLACCLSubframeTask) * 32 * channelsCount * MAX_FRAMES;
@@ -2836,9 +2780,10 @@ namespace CUETools.Codecs.FLACCL
internal unsafe void EnqueueKernels() internal unsafe void EnqueueKernels()
{ {
FlakeEncodeParams eparams = writer.eparams; var eparams = writer.eparams;
var settings = writer.Settings as FLACCLWriterSettings;
this.max_porder = FLACCLWriter.get_max_p_order(eparams.max_partition_order, frameSize, eparams.max_prediction_order); this.max_porder = FLACCLWriter.get_max_p_order(settings.MaxPartitionOrder, frameSize, settings.MaxLPCOrder);
while ((frameSize >> max_porder) < 16 && max_porder > 0) while ((frameSize >> max_porder) < 16 && max_porder > 0)
this.max_porder--; this.max_porder--;

View File

@@ -38,7 +38,12 @@ namespace CUETools.Codecs.FLAKE
8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
0, 0, 0, 0 0, 0, 0, 0
}; };
//1100 : get 8 bit sample rate (in kHz) from end of header
//1101 : get 16 bit sample rate (in Hz) from end of header
//1110 : get 16 bit sample rate (in tens of Hz) from end of header
public static readonly int[] flac_blocksizes = new int[15] { 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384 }; public static readonly int[] flac_blocksizes = new int[15] { 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384 };
//0110 : get 8 bit (blocksize-1) from end of header
//0111 : get 16 bit (blocksize-1) from end of header
public static readonly int[] flac_bitdepths = new int[8] { 0, 8, 12, 0, 16, 20, 24, 0 }; public static readonly int[] flac_bitdepths = new int[8] { 0, 8, 12, 0, 16, 20, 24, 0 };
public static PredictionType LookupPredictionType(string name) public static PredictionType LookupPredictionType(string name)

View File

@@ -44,16 +44,129 @@ namespace CUETools.Codecs.FLAKE
public override string GetSupportedModes(out string defaultMode) public override string GetSupportedModes(out string defaultMode)
{ {
defaultMode = "7"; defaultMode = "7";
return this.AllowNonSubset ? "0 1 2 3 4 5 6 7 8 9 10 11" : "0 1 2 3 4 5 6 7 8"; return this.AllowNonSubset || (this.PCM != null && this.PCM.SampleRate > 48000) ? "0 1 2 3 4 5 6 7 8 9 10 11" : "0 1 2 3 4 5 6 7 8";
} }
public override bool IsValid() public bool IsSubset()
{ {
return EncoderModeIndex >= 0 && Padding >= 0 && return (BlockSize == 0 || (BlockSize <= 16384 && (PCM.SampleRate > 48000 || BlockSize <= 4608)))
(BlockSize == 0 || (BlockSize >= 256 && BlockSize <= Flake.MAX_BLOCKSIZE)) && && (PCM.SampleRate > 48000 || MaxLPCOrder <= 12)
(AllowNonSubset || EncoderModeIndex <= 8); && MaxPartitionOrder <= 8
;
//The blocksize bits in the frame header must be 0001-1110. The blocksize must be <=16384; if the sample rate is <= 48000Hz, the blocksize must be <=4608.
//The sample rate bits in the frame header must be 0001-1110.
//The bits-per-sample bits in the frame header must be 001-111.
//If the sample rate is <= 48000Hz, the filter order in LPC subframes must be less than or equal to 12, i.e. the subframe type bits in the subframe header may not be 101100-111111.
//The Rice partition order in a Rice-coded residual section must be less than or equal to 8.
} }
public void Validate()
{
if (EncoderModeIndex < 0)
throw new Exception("unsupported encoder mode");
var thisModeSettings = FlakeWriterSettings.modeSettings[EncoderModeIndex];
if (MaxLPCOrder < 0)
MaxLPCOrder = thisModeSettings.MaxLPCOrder;
if (MinFixedOrder < 0)
MinFixedOrder = thisModeSettings.MinFixedOrder;
if (MaxFixedOrder < 0)
MaxFixedOrder = thisModeSettings.MaxFixedOrder;
if (MaxPartitionOrder < 0)
MaxPartitionOrder = thisModeSettings.MaxPartitionOrder;
if (Padding < 0)
throw new Exception("unsupported padding value " + Padding.ToString());
if (BlockSize != 0 && (BlockSize < 256 || BlockSize >= Flake.MAX_BLOCKSIZE))
throw new Exception("unsupported block size " + BlockSize.ToString());
if (MinLPCOrder > MaxLPCOrder || MaxLPCOrder > lpc.MAX_LPC_ORDER)
throw new Exception("invalid MaxLPCOrder " + MaxLPCOrder.ToString());
if (MinFixedOrder < 0 || MinFixedOrder > 4)
throw new Exception("invalid MinFixedOrder " + MinFixedOrder.ToString());
if (MaxFixedOrder < 0 || MaxFixedOrder > 4)
throw new Exception("invalid MaxFixedOrder " + MaxFixedOrder.ToString());
if (MinPartitionOrder < 0)
throw new Exception("invalid MinPartitionOrder " + MinPartitionOrder.ToString());
if (MinPartitionOrder > MaxPartitionOrder || MaxPartitionOrder > 8)
throw new Exception("invalid MaxPartitionOrder " + MaxPartitionOrder.ToString());
if (!AllowNonSubset && !IsSubset())
throw new Exception("the encoding parameters specified do not conform to the FLAC Subset");
}
private static FlakeWriterSettings[] modeSettings =
{
new FlakeWriterSettings() {
MinFixedOrder = 3, MaxFixedOrder = 2, MaxLPCOrder = 6, MaxPartitionOrder = 6,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 8, MaxPartitionOrder = 6,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12, MaxPartitionOrder = 6,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 8, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 12, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 0, MaxFixedOrder = 2, MaxLPCOrder = 12, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 2, MaxFixedOrder = 2, MaxLPCOrder = 32, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 0, MaxFixedOrder = 4, MaxLPCOrder = 32, MaxPartitionOrder = 8,
},
new FlakeWriterSettings() {
MinFixedOrder = 0, MaxFixedOrder = 4, MaxLPCOrder = 32, MaxPartitionOrder = 8,
},
};
[DefaultValue(-1)]
[Browsable(false)]
[DisplayName("MinFixedOrder")]
[SRDescription(typeof(Properties.Resources), "MinFixedOrderDescription")]
public int MinFixedOrder { get; set; }
[DefaultValue(-1)]
[Browsable(false)]
[DisplayName("MaxFixedOrder")]
[SRDescription(typeof(Properties.Resources), "MaxFixedOrderDescription")]
public int MaxFixedOrder { get; set; }
[DefaultValue(1)]
[Browsable(false)]
[DisplayName("MinLPCOrder")]
[SRDescription(typeof(Properties.Resources), "MinLPCOrderDescription")]
public int MinLPCOrder { get; set; }
[DefaultValue(-1)]
[Browsable(false)]
[DisplayName("MaxLPCOrder")]
[SRDescription(typeof(Properties.Resources), "MaxLPCOrderDescription")]
public int MaxLPCOrder { get; set; }
[DefaultValue(0)]
[DisplayName("MinPartitionOrder")]
[Browsable(false)]
[SRDescription(typeof(Properties.Resources), "MinPartitionOrderDescription")]
public int MinPartitionOrder { get; set; }
[DefaultValue(-1)]
[DisplayName("MaxPartitionOrder")]
[Browsable(false)]
[SRDescription(typeof(Properties.Resources), "MaxPartitionOrderDescription")]
public int MaxPartitionOrder { get; set; }
[DefaultValue(false)] [DefaultValue(false)]
[DisplayName("Verify")] [DisplayName("Verify")]
[SRDescription(typeof(Properties.Resources), "DoVerifyDescription")] [SRDescription(typeof(Properties.Resources), "DoVerifyDescription")]
@@ -142,7 +255,8 @@ namespace CUETools.Codecs.FLAKE
public FlakeWriter(string path, Stream IO, FlakeWriterSettings settings) public FlakeWriter(string path, Stream IO, FlakeWriterSettings settings)
{ {
m_settings = settings; m_settings = settings.Clone() as FlakeWriterSettings;
m_settings.Validate();
//if (Settings.PCM.BitsPerSample != 16) //if (Settings.PCM.BitsPerSample != 16)
// throw new Exception("Bits per sample must be 16."); // throw new Exception("Bits per sample must be 16.");
@@ -161,8 +275,7 @@ namespace CUETools.Codecs.FLAKE
windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS]; windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
windowScale = new double[lpc.MAX_LPC_WINDOWS]; windowScale = new double[lpc.MAX_LPC_WINDOWS];
var _compressionLevel = Settings.EncoderModeIndex; eparams.flake_set_defaults(m_settings);
eparams.flake_set_defaults(_compressionLevel);
crc8 = new Crc8(); crc8 = new Crc8();
frame = new FlacFrame(channels * 2); frame = new FlacFrame(channels * 2);
@@ -346,70 +459,6 @@ namespace CUETools.Codecs.FLAKE
set { eparams.variable_block_size = value; } set { eparams.variable_block_size = value; }
} }
public int MinPredictionOrder
{
get
{
return PredictionType == PredictionType.Fixed ?
MinFixedOrder : MinLPCOrder;
}
set
{
if (PredictionType == PredictionType.Fixed)
MinFixedOrder = value;
else
MinLPCOrder = value;
}
}
public int MaxPredictionOrder
{
get
{
return PredictionType == PredictionType.Fixed ?
MaxFixedOrder : MaxLPCOrder;
}
set
{
if (PredictionType == PredictionType.Fixed)
MaxFixedOrder = value;
else
MaxLPCOrder = value;
}
}
public int MinLPCOrder
{
get
{
return eparams.min_prediction_order;
}
set
{
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;
}
}
public int MaxLPCOrder
{
get
{
return eparams.max_prediction_order;
}
set
{
if (value > lpc.MAX_LPC_ORDER)
throw new Exception("invalid MaxLPCOrder " + value.ToString());
if (eparams.min_prediction_order > value)
eparams.min_prediction_order = value;
eparams.max_prediction_order = value;
}
}
public int EstimationDepth public int EstimationDepth
{ {
get get
@@ -424,56 +473,6 @@ namespace CUETools.Codecs.FLAKE
} }
} }
public int MinFixedOrder
{
get
{
return eparams.min_fixed_order;
}
set
{
if (value < 0 || value > eparams.max_fixed_order)
throw new Exception("invalid MinFixedOrder " + value.ToString());
eparams.min_fixed_order = value;
}
}
public int MaxFixedOrder
{
get
{
return eparams.max_fixed_order;
}
set
{
if (value > 4 || value < eparams.min_fixed_order)
throw new Exception("invalid MaxFixedOrder " + value.ToString());
eparams.max_fixed_order = value;
}
}
public int MinPartitionOrder
{
get { return eparams.min_partition_order; }
set
{
if (value < 0 || value > eparams.max_partition_order)
throw new Exception("invalid MinPartitionOrder " + value.ToString());
eparams.min_partition_order = value;
}
}
public int MaxPartitionOrder
{
get { return eparams.max_partition_order; }
set
{
if (value > 8 || value < eparams.min_partition_order)
throw new Exception("invalid MaxPartitionOrder " + value.ToString());
eparams.max_partition_order = value;
}
}
public TimeSpan UserProcessorTime public TimeSpan UserProcessorTime
{ {
get get
@@ -904,8 +903,8 @@ new int[] { // 30
int orig_xx = -1; int orig_xx = -1;
int orig_seq = 0; int orig_seq = 0;
int maxxx = Math.Min(good_x[orig_order].Length, eparams.development_mode); 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 pmax = get_max_p_order(m_settings.MaxPartitionOrder, frame.blocksize, orig_order);
var pmin = Math.Min(eparams.min_partition_order, pmax); var pmin = Math.Min(m_settings.MinPartitionOrder, pmax);
ulong* sums = stackalloc ulong[(pmax + 1) * Flake.MAX_PARTITIONS]; ulong* sums = stackalloc ulong[(pmax + 1) * Flake.MAX_PARTITIONS];
while (true) while (true)
@@ -1084,8 +1083,8 @@ new int[] { // 30
lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); 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 pmax = get_max_p_order(m_settings.MaxPartitionOrder, frame.blocksize, frame.current.order);
int pmin = Math.Min(eparams.min_partition_order, pmax); int pmin = Math.Min(m_settings.MinPartitionOrder, pmax);
uint best_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample); uint best_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample);
// not working // not working
//for (int o = 1; o <= frame.current.order; o++) //for (int o = 1; o <= frame.current.order; o++)
@@ -1126,8 +1125,8 @@ new int[] { // 30
encode_residual_fixed(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order); encode_residual_fixed(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order);
int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order); int pmax = get_max_p_order(m_settings.MaxPartitionOrder, frame.blocksize, frame.current.order);
int pmin = Math.Min(eparams.min_partition_order, pmax); int pmin = Math.Min(m_settings.MinPartitionOrder, pmax);
frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits) + 6 frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits) + 6
+ calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample); + calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample);
@@ -1164,7 +1163,7 @@ new int[] { // 30
return; return;
// LPC // LPC
if (n > eparams.max_prediction_order && if (n > m_settings.MaxLPCOrder &&
(predict == PredictionType.Levinson || (predict == PredictionType.Levinson ||
predict == PredictionType.Search) predict == PredictionType.Search)
//predict == PredictionType.Search || //predict == PredictionType.Search ||
@@ -1172,8 +1171,8 @@ new int[] { // 30
) )
{ {
float* lpcs = stackalloc float[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER]; float* lpcs = stackalloc float[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER];
int min_order = eparams.min_prediction_order; int min_order = m_settings.MinLPCOrder;
int max_order = eparams.max_prediction_order; int max_order = m_settings.MaxLPCOrder;
for (int iWindow = 0; iWindow < _windowcount; iWindow++) for (int iWindow = 0; iWindow < _windowcount; iWindow++)
{ {
@@ -1257,10 +1256,10 @@ new int[] { // 30
(predict == PredictionType.Search && pass != 1) || (predict == PredictionType.Search && pass != 1) ||
//predict == PredictionType.Search || //predict == PredictionType.Search ||
//(pass == 2 && frame.subframes[ch].best.type == SubframeType.Fixed) || //(pass == 2 && frame.subframes[ch].best.type == SubframeType.Fixed) ||
(n > eparams.max_fixed_order && n <= eparams.max_prediction_order)) (n > m_settings.MaxFixedOrder && n <= m_settings.MaxLPCOrder))
{ {
int max_fixed_order = Math.Min(eparams.max_fixed_order, 4); int max_fixed_order = Math.Min(m_settings.MaxFixedOrder, 4);
int min_fixed_order = Math.Min(eparams.min_fixed_order, max_fixed_order); int min_fixed_order = Math.Min(m_settings.MinFixedOrder, max_fixed_order);
for (i = min_fixed_order; i <= max_fixed_order; i++) for (i = min_fixed_order; i <= max_fixed_order; i++)
encode_residual_fixed_sub(frame, i, ch); encode_residual_fixed_sub(frame, i, ch);
@@ -1426,27 +1425,27 @@ new int[] { // 30
unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window) unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window)
{ {
int max_prediction_order = eparams.max_prediction_order; int max_prediction_order = m_settings.MaxLPCOrder;
int max_fixed_order = eparams.max_fixed_order; int max_fixed_order = m_settings.MaxFixedOrder;
int min_fixed_order = eparams.min_fixed_order; int min_fixed_order = m_settings.MinFixedOrder;
int lpc_min_precision_search = eparams.lpc_min_precision_search; int lpc_min_precision_search = eparams.lpc_min_precision_search;
int lpc_max_precision_search = eparams.lpc_max_precision_search; int lpc_max_precision_search = eparams.lpc_max_precision_search;
int max_partition_order = eparams.max_partition_order; int max_partition_order = m_settings.MaxPartitionOrder;
int estimation_depth = eparams.estimation_depth; int estimation_depth = eparams.estimation_depth;
var development_mode = eparams.development_mode; var development_mode = eparams.development_mode;
eparams.min_fixed_order = 2; m_settings.MinFixedOrder = 2;
eparams.max_fixed_order = 2; m_settings.MaxFixedOrder = 2;
eparams.lpc_min_precision_search = eparams.lpc_max_precision_search; eparams.lpc_min_precision_search = eparams.lpc_max_precision_search;
eparams.max_prediction_order = Math.Min(eparams.max_prediction_order, Math.Max(eparams.min_prediction_order, 8)); m_settings.MaxLPCOrder = Math.Min(m_settings.MaxLPCOrder, Math.Max(m_settings.MinLPCOrder, 8));
eparams.estimation_depth = 1; eparams.estimation_depth = 1;
eparams.development_mode = Math.Min(eparams.development_mode, -1); eparams.development_mode = Math.Min(eparams.development_mode, -1);
encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window); encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window);
eparams.min_fixed_order = min_fixed_order; m_settings.MinFixedOrder = min_fixed_order;
eparams.max_fixed_order = max_fixed_order; m_settings.MaxFixedOrder = max_fixed_order;
eparams.max_prediction_order = max_prediction_order; m_settings.MaxLPCOrder = max_prediction_order;
eparams.lpc_min_precision_search = lpc_min_precision_search; eparams.lpc_min_precision_search = lpc_min_precision_search;
eparams.lpc_max_precision_search = lpc_max_precision_search; eparams.lpc_max_precision_search = lpc_max_precision_search;
eparams.max_partition_order = max_partition_order; m_settings.MaxPartitionOrder = max_partition_order;
eparams.estimation_depth = estimation_depth; eparams.estimation_depth = estimation_depth;
eparams.development_mode = development_mode; eparams.development_mode = development_mode;
} }
@@ -1501,7 +1500,7 @@ new int[] { // 30
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0]; LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0];
lpc_ctx.GetReflection(4, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer); lpc_ctx.GetReflection(4, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer);
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 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); 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 * m_settings.MaxLPCOrder);
} }
break; break;
case StereoMethod.Evaluate: case StereoMethod.Evaluate:
@@ -1779,8 +1778,6 @@ new int[] { // 30
{ {
if (_IO == null) if (_IO == null)
_IO = new FileStream(_path, FileMode.Create, FileAccess.Write, FileShare.Read); _IO = new FileStream(_path, FileMode.Create, FileAccess.Write, FileShare.Read);
if (!m_settings.IsValid())
throw new Exception("unsupported encoder settings");
inited = true; inited = true;
int header_size = flake_encode_init(); int header_size = flake_encode_init();
_IO.Write(header, 0, header_size); _IO.Write(header, 0, header_size);
@@ -1836,7 +1833,7 @@ new int[] { // 30
return blocksize >> 1; return blocksize >> 1;
} }
for (int i = 0; i < Flake.flac_blocksizes.Length; i++) for (int i = 8; i < Flake.flac_blocksizes.Length - 1; i++)
if (target >= Flake.flac_blocksizes[i] && Flake.flac_blocksizes[i] > blocksize) if (target >= Flake.flac_blocksizes[i] && Flake.flac_blocksizes[i] > blocksize)
{ {
blocksize = Flake.flac_blocksizes[i]; blocksize = Flake.flac_blocksizes[i];
@@ -2057,15 +2054,6 @@ new int[] { // 30
struct FlakeEncodeParams struct FlakeEncodeParams
{ {
// compression quality
// set by user prior to calling flake_encode_init
// standard values are 0 to 8
// 0 is lower compression, faster encoding
// 8 is higher compression, slower encoding
// extended values 9 to 12 are slower and/or use
// higher prediction orders
public int compression;
// prediction order selection method // prediction order selection method
// 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.
@@ -2079,7 +2067,6 @@ new int[] { // 30
// 6 = log search // 6 = log search
public OrderMethod order_method; public OrderMethod order_method;
// stereo decorrelation method // stereo decorrelation method
// 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.
@@ -2096,52 +2083,16 @@ new int[] { // 30
// can also be changed by user before encoding a frame // can also be changed by user before encoding a frame
public int block_time_ms; public int block_time_ms;
// minimum LPC order
// 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 min_prediction_order;
// maximum LPC order
// 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 max_prediction_order;
// Number of LPC orders to try (for estimate mode) // Number of LPC orders to try (for estimate mode)
// 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.
// valid values are 1 to 32 // valid values are 1 to 32
public int estimation_depth; 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.
// valid values are 0 to 4
public int min_fixed_order;
// maximum fixed prediction order
// set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression.
// valid values are 0 to 4
public int max_fixed_order;
// type of linear prediction // type of linear prediction
// set by user prior to calling flake_encode_init // set by user prior to calling flake_encode_init
public PredictionType prediction_type; public PredictionType prediction_type;
// minimum partition order
// set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression.
// valid values are 0 to 8
public int min_partition_order;
// maximum partition order
// set by user prior to calling flake_encode_init
// if set to less than 0, it is chosen based on compression.
// valid values are 0 to 8
public int max_partition_order;
// whether to use variable block sizes // whether to use variable block sizes
// set by user prior to calling flake_encode_init // set by user prior to calling flake_encode_init
// 0 = fixed block size // 0 = fixed block size
@@ -2161,60 +2112,42 @@ new int[] { // 30
public int development_mode; public int development_mode;
public int flake_set_defaults(int lvl) public int flake_set_defaults(FlakeWriterSettings settings)
{ {
compression = lvl; // default to level 7 params
if ((lvl < 0 || lvl > 12) && (lvl != 99))
{
return -1;
}
// default to level 5 params
window_function = WindowFunction.Flattop | WindowFunction.Tukey; window_function = WindowFunction.Flattop | WindowFunction.Tukey;
order_method = OrderMethod.Akaike; order_method = OrderMethod.Akaike;
stereo_method = StereoMethod.Evaluate; stereo_method = StereoMethod.Evaluate;
window_method = WindowMethod.Evaluate; window_method = WindowMethod.Evaluate;
block_time_ms = 105; block_time_ms = 105;
prediction_type = PredictionType.Search; prediction_type = PredictionType.Search;
min_prediction_order = 1; estimation_depth = 1;
max_prediction_order = 12; variable_block_size = 0;
estimation_depth = 1;
min_fixed_order = 2;
max_fixed_order = 2;
min_partition_order = 0;
max_partition_order = 8;
variable_block_size = 0;
lpc_min_precision_search = 1; lpc_min_precision_search = 1;
lpc_max_precision_search = 1; lpc_max_precision_search = 1;
do_seektable = true; do_seektable = true;
development_mode = -1; development_mode = -1;
// differences from level 7 // differences from level 7
switch (lvl) switch (settings.EncoderModeIndex)
{ {
case 0: case 0:
block_time_ms = 53; block_time_ms = 53;
prediction_type = PredictionType.Fixed; prediction_type = PredictionType.Fixed;
stereo_method = StereoMethod.Independent; stereo_method = StereoMethod.Independent;
max_partition_order = 6;
break; break;
case 1: case 1:
prediction_type = PredictionType.Levinson; prediction_type = PredictionType.Levinson;
stereo_method = StereoMethod.Independent; stereo_method = StereoMethod.Independent;
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
max_prediction_order = 8;
max_partition_order = 6;
break; break;
case 2: case 2:
stereo_method = StereoMethod.Independent; stereo_method = StereoMethod.Independent;
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
max_partition_order = 6;
break; break;
case 3: case 3:
stereo_method = StereoMethod.Estimate; stereo_method = StereoMethod.Estimate;
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
max_prediction_order = 8;
break; break;
case 4: case 4:
stereo_method = StereoMethod.Estimate; stereo_method = StereoMethod.Estimate;
@@ -2231,23 +2164,15 @@ new int[] { // 30
break; break;
case 8: case 8:
estimation_depth = 2; estimation_depth = 2;
min_fixed_order = 0;
lpc_min_precision_search = 0; lpc_min_precision_search = 0;
break; break;
case 9: case 9:
window_function = WindowFunction.Bartlett; window_function = WindowFunction.Bartlett;
max_prediction_order = 32;
break; break;
case 10: case 10:
min_fixed_order = 0;
max_fixed_order = 4;
max_prediction_order = 32;
//lpc_max_precision_search = 2; //lpc_max_precision_search = 2;
break; break;
case 11: case 11:
min_fixed_order = 0;
max_fixed_order = 4;
max_prediction_order = 32;
estimation_depth = 5; estimation_depth = 5;
//lpc_max_precision_search = 2; //lpc_max_precision_search = 2;
variable_block_size = 4; variable_block_size = 4;

View File

@@ -46,17 +46,6 @@ namespace CUETools.Codecs
return this.m_supported_modes; return this.m_supported_modes;
} }
public virtual bool IsValid()
{
return BlockSize == 0 && Padding >= 0;
}
public void Validate()
{
if (!IsValid())
throw new Exception("unsupported encoder settings");
}
public AudioEncoderSettings Clone() public AudioEncoderSettings Clone()
{ {
return this.MemberwiseClone() as AudioEncoderSettings; return this.MemberwiseClone() as AudioEncoderSettings;

View File

@@ -172,7 +172,6 @@ namespace CUETools.Converter
settings.PCM = audioSource.PCM; settings.PCM = audioSource.PCM;
settings.Padding = padding; settings.Padding = padding;
settings.EncoderMode = encoderMode ?? settings.EncoderMode; settings.EncoderMode = encoderMode ?? settings.EncoderMode;
settings.Validate();
object o = null; object o = null;
try try
{ {

View File

@@ -82,10 +82,7 @@ namespace CUETools.FLACCL.cmd
string input_file = null; string input_file = null;
string output_file = null; string output_file = null;
string device_type = null; string device_type = null;
int min_partition_order = -1, max_partition_order = -1, int min_precision = -1, max_precision = -1,
min_lpc_order = -1, max_lpc_order = -1,
min_fixed_order = -1, max_fixed_order = -1,
min_precision = -1, max_precision = -1,
orders_per_window = -1, orders_per_channel = -1; orders_per_window = -1, orders_per_channel = -1;
int input_len = 4096, input_val = 0, input_bps = 16, input_ch = 2, input_rate = 44100; int input_len = 4096, input_val = 0, input_bps = 16, input_ch = 2, input_rate = 44100;
int level = -1, vbr_mode = -1; int level = -1, vbr_mode = -1;
@@ -152,43 +149,55 @@ namespace CUETools.FLACCL.cmd
window_function = args[arg]; window_function = args[arg];
else if ((args[arg] == "-r" || args[arg] == "--partition-order") && ++arg < args.Length) else if ((args[arg] == "-r" || args[arg] == "--partition-order") && ++arg < args.Length)
{ {
ok = (args[arg].Split(',').Length == 2 && int min_partition_order, max_partition_order;
int.TryParse(args[arg].Split(',')[0], out min_partition_order) && ok = (args[arg].Split(',').Length == 2
int.TryParse(args[arg].Split(',')[1], out max_partition_order)) || && int.TryParse(args[arg].Split(',')[0], out min_partition_order)
int.TryParse(args[arg], out max_partition_order); && (settings.MinPartitionOrder = min_partition_order) != -1
&& int.TryParse(args[arg].Split(',')[1], out max_partition_order)
&& (settings.MaxPartitionOrder = max_partition_order) != -1)
|| (int.TryParse(args[arg], out max_partition_order)
&& (settings.MaxPartitionOrder = max_partition_order) != -1);
} }
else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length) else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length)
{ {
ok = (args[arg].Split(',').Length == 2 && int min_lpc_order, max_lpc_order;
int.TryParse(args[arg].Split(',')[0], out min_lpc_order) && ok = (args[arg].Split(',').Length == 2
int.TryParse(args[arg].Split(',')[1], out max_lpc_order)) || && int.TryParse(args[arg].Split(',')[0], out min_lpc_order)
int.TryParse(args[arg], out max_lpc_order); && (settings.MinLPCOrder = min_lpc_order) != -1
&& int.TryParse(args[arg].Split(',')[1], out max_lpc_order)
&& (settings.MaxLPCOrder = max_lpc_order) != -1)
|| (int.TryParse(args[arg], out max_lpc_order)
&& (settings.MaxLPCOrder = max_lpc_order) != -1);
} }
else if (args[arg] == "--fixed-order" && ++arg < args.Length) else if (args[arg] == "--fixed-order" && ++arg < args.Length)
{ {
ok = (args[arg].Split(',').Length == 2 && int min_fixed_order, max_fixed_order;
int.TryParse(args[arg].Split(',')[0], out min_fixed_order) && ok = (args[arg].Split(',').Length == 2
int.TryParse(args[arg].Split(',')[1], out max_fixed_order)) || && int.TryParse(args[arg].Split(',')[0], out min_fixed_order)
int.TryParse(args[arg], out max_fixed_order); && (settings.MinFixedOrder = min_fixed_order) != -1
} && int.TryParse(args[arg].Split(',')[1], out max_fixed_order)
else if ((args[arg] == "-c" || args[arg] == "--max-precision") && ++arg < args.Length) && (settings.MaxFixedOrder = max_fixed_order) != -1)
{ || (int.TryParse(args[arg], out max_fixed_order)
ok = (args[arg].Split(',').Length == 2 && && (settings.MaxFixedOrder = max_fixed_order) != -1);
int.TryParse(args[arg].Split(',')[0], out min_precision) && }
int.TryParse(args[arg].Split(',')[1], out max_precision)) || else if ((args[arg] == "-c" || args[arg] == "--max-precision") && ++arg < args.Length)
int.TryParse(args[arg], out max_precision); {
} ok = (args[arg].Split(',').Length == 2 &&
else if ((args[arg] == "-v" || args[arg] == "--vbr")) int.TryParse(args[arg].Split(',')[0], out min_precision) &&
ok = (++arg < args.Length) && int.TryParse(args[arg], out vbr_mode); int.TryParse(args[arg].Split(',')[1], out max_precision)) ||
else if (args[arg] == "--orders-per-window" && ++arg < args.Length && int.TryParse(args[arg], out intarg)) int.TryParse(args[arg], out max_precision);
orders_per_window = intarg; }
else if (args[arg] == "--orders-per-channel" && ++arg < args.Length && int.TryParse(args[arg], out intarg)) else if ((args[arg] == "-v" || args[arg] == "--vbr"))
orders_per_channel = intarg; ok = (++arg < args.Length) && int.TryParse(args[arg], out vbr_mode);
else if (args[arg] == "--estimate-window") else if (args[arg] == "--orders-per-window" && ++arg < args.Length && int.TryParse(args[arg], out intarg))
estimate_window = true; orders_per_window = intarg;
else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length && int.TryParse(args[arg], out intarg)) else if (args[arg] == "--orders-per-channel" && ++arg < args.Length && int.TryParse(args[arg], out intarg))
orders_per_channel = intarg;
else if (args[arg] == "--estimate-window")
estimate_window = true;
else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length && int.TryParse(args[arg], out intarg))
settings.BlockSize = intarg; settings.BlockSize = intarg;
else if ((args[arg] == "-p" || args[arg] == "--padding") && ++arg < args.Length && int.TryParse(args[arg], out intarg)) else if ((args[arg] == "-p" || args[arg] == "--padding") && ++arg < args.Length && int.TryParse(args[arg], out intarg))
settings.Padding = intarg; settings.Padding = intarg;
else if (args[arg] != "-" && args[arg][0] == '-' && int.TryParse(args[arg].Substring(1), out level)) else if (args[arg] != "-" && args[arg][0] == '-' && int.TryParse(args[arg].Substring(1), out level))
{ {
@@ -253,35 +262,21 @@ namespace CUETools.FLACCL.cmd
output_file = Path.ChangeExtension(input_file, "flac"); output_file = Path.ChangeExtension(input_file, "flac");
settings.PCM = audioSource.PCM; settings.PCM = audioSource.PCM;
settings.AllowNonSubset = allowNonSubset; settings.AllowNonSubset = allowNonSubset;
FLACCLWriter encoder = new FLACCLWriter((output_file == "-" || output_file == "nul") ? "" : output_file, FLACCLWriter encoder;
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
settings);
encoder.FinalSampleCount = audioSource.Length;
IAudioDest audioDest = encoder;
AudioBuffer buff = new AudioBuffer(audioSource, FLACCLWriter.MAX_BLOCKSIZE);
try try
{ {
if (device_type != null) if (device_type != null)
settings.DeviceType = (OpenCLDeviceType)(Enum.Parse(typeof(OpenCLDeviceType), device_type, true)); settings.DeviceType = (OpenCLDeviceType)(Enum.Parse(typeof(OpenCLDeviceType), device_type, true));
settings.Validate(); encoder = new FLACCLWriter((output_file == "-" || output_file == "nul") ? "" : output_file,
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
settings);
encoder.FinalSampleCount = audioSource.Length;
if (stereo_method != null) if (stereo_method != null)
encoder.StereoMethod = Flake.LookupStereoMethod(stereo_method); encoder.StereoMethod = Flake.LookupStereoMethod(stereo_method);
if (window_function != null) if (window_function != null)
encoder.WindowFunction = Flake.LookupWindowFunction(window_function); encoder.WindowFunction = Flake.LookupWindowFunction(window_function);
if (min_partition_order >= 0)
encoder.MinPartitionOrder = min_partition_order;
if (max_partition_order >= 0)
encoder.MaxPartitionOrder = max_partition_order;
if (min_lpc_order >= 0)
encoder.MinLPCOrder = min_lpc_order;
if (max_lpc_order >= 0)
encoder.MaxLPCOrder = max_lpc_order;
if (min_fixed_order >= 0)
encoder.MinFixedOrder = min_fixed_order;
if (max_fixed_order >= 0)
encoder.MaxFixedOrder = max_fixed_order;
if (max_precision >= 0) if (max_precision >= 0)
encoder.MaxPrecisionSearch = max_precision; encoder.MaxPrecisionSearch = max_precision;
if (min_precision >= 0) if (min_precision >= 0)
@@ -304,6 +299,9 @@ namespace CUETools.FLACCL.cmd
return 3; return 3;
} }
IAudioDest audioDest = encoder;
AudioBuffer buff = new AudioBuffer(audioSource, FLACCLWriter.MAX_BLOCKSIZE);
if (!quiet) if (!quiet)
{ {
Console.WriteLine("Filename : {0}", input_file); Console.WriteLine("Filename : {0}", input_file);
@@ -393,15 +391,15 @@ namespace CUETools.FLACCL.cmd
encoder.UserProcessorTime.TotalSeconds > 0 ? encoder.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds, encoder.UserProcessorTime.TotalSeconds > 0 ? encoder.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds,
(encoder.StereoMethod.ToString() + (encoder.OrdersPerChannel == 32 ? "" : "(" + encoder.OrdersPerChannel.ToString() + ")")).PadRight(15), (encoder.StereoMethod.ToString() + (encoder.OrdersPerChannel == 32 ? "" : "(" + encoder.OrdersPerChannel.ToString() + ")")).PadRight(15),
encoder.WindowFunction.ToString().PadRight(15), encoder.WindowFunction.ToString().PadRight(15),
encoder.MaxPartitionOrder, settings.MaxPartitionOrder,
settings.GPUOnly ? "GPU" : "CPU", settings.GPUOnly ? "GPU" : "CPU",
encoder.OrdersPerWindow, encoder.OrdersPerWindow,
encoder.MaxLPCOrder, (encoder.Settings as FLACCLWriterSettings).MaxLPCOrder,
encoder.MinPrecisionSearch, encoder.MinPrecisionSearch,
encoder.MaxPrecisionSearch, encoder.MaxPrecisionSearch,
encoder.Settings.BlockSize, encoder.Settings.BlockSize,
encoder.VBRMode, encoder.VBRMode,
encoder.MaxFixedOrder - encoder.MinFixedOrder + 1, (encoder.Settings as FLACCLWriterSettings).MaxFixedOrder - (encoder.Settings as FLACCLWriterSettings).MinFixedOrder + 1,
encoder.DoConstant ? "c" : "" encoder.DoConstant ? "c" : ""
); );
} }

View File

@@ -138,10 +138,7 @@ namespace CUETools.FlakeExe
string window_function = null; string window_function = null;
string input_file = null; string input_file = null;
string output_file = null; string output_file = null;
int min_partition_order = -1, max_partition_order = -1, int min_precision = -1, max_precision = -1,
min_lpc_order = -1, max_lpc_order = -1,
min_fixed_order = -1, max_fixed_order = -1,
min_precision = -1, max_precision = -1,
estimation_depth = -1; estimation_depth = -1;
int skip_a = 0, skip_b = 0; int skip_a = 0, skip_b = 0;
int intarg = -1, vbr_mode = -1, magic = -1; int intarg = -1, vbr_mode = -1, magic = -1;
@@ -187,24 +184,36 @@ namespace CUETools.FlakeExe
window_method = args[arg]; window_method = args[arg];
else if ((args[arg] == "-r" || args[arg] == "--partition-order") && ++arg < args.Length) else if ((args[arg] == "-r" || args[arg] == "--partition-order") && ++arg < args.Length)
{ {
ok = (args[arg].Split(',').Length == 2 && int min_partition_order, max_partition_order;
int.TryParse(args[arg].Split(',')[0], out min_partition_order) && ok = (args[arg].Split(',').Length == 2
int.TryParse(args[arg].Split(',')[1], out max_partition_order)) || && int.TryParse(args[arg].Split(',')[0], out min_partition_order)
int.TryParse(args[arg], out max_partition_order); && (settings.MinPartitionOrder = min_partition_order) != -1
&& int.TryParse(args[arg].Split(',')[1], out max_partition_order)
&& (settings.MaxPartitionOrder = max_partition_order) != -1)
|| (int.TryParse(args[arg], out max_partition_order)
&& (settings.MaxPartitionOrder = max_partition_order) != -1);
} }
else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length) else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length)
{ {
ok = (args[arg].Split(',').Length == 2 && int min_lpc_order, max_lpc_order;
int.TryParse(args[arg].Split(',')[0], out min_lpc_order) && ok = (args[arg].Split(',').Length == 2
int.TryParse(args[arg].Split(',')[1], out max_lpc_order)) || && int.TryParse(args[arg].Split(',')[0], out min_lpc_order)
int.TryParse(args[arg], out max_lpc_order); && (settings.MinLPCOrder = min_lpc_order) != -1
&& int.TryParse(args[arg].Split(',')[1], out max_lpc_order)
&& (settings.MaxLPCOrder = max_lpc_order) != -1)
|| (int.TryParse(args[arg], out max_lpc_order)
&& (settings.MaxLPCOrder = max_lpc_order) != -1);
} }
else if ((args[arg] == "-f" || args[arg] == "--fixed-order") && ++arg < args.Length) else if ((args[arg] == "-f" || args[arg] == "--fixed-order") && ++arg < args.Length)
{ {
ok = (args[arg].Split(',').Length == 2 && int min_fixed_order, max_fixed_order;
int.TryParse(args[arg].Split(',')[0], out min_fixed_order) && ok = (args[arg].Split(',').Length == 2
int.TryParse(args[arg].Split(',')[1], out max_fixed_order)) || && int.TryParse(args[arg].Split(',')[0], out min_fixed_order)
int.TryParse(args[arg], out max_fixed_order); && (settings.MinFixedOrder = min_fixed_order) != -1
&& int.TryParse(args[arg].Split(',')[1], out max_fixed_order)
&& (settings.MaxFixedOrder = max_fixed_order) != -1)
|| (int.TryParse(args[arg], out max_fixed_order)
&& (settings.MaxFixedOrder = max_fixed_order) != -1);
} }
else if (args[arg] == "--skip" && ++arg < args.Length) else if (args[arg] == "--skip" && ++arg < args.Length)
{ {
@@ -329,17 +338,16 @@ namespace CUETools.FlakeExe
output_file = Path.ChangeExtension(input_file, "flac"); output_file = Path.ChangeExtension(input_file, "flac");
settings.PCM = audioSource.PCM; settings.PCM = audioSource.PCM;
settings.AllowNonSubset = allowNonSubset; settings.AllowNonSubset = allowNonSubset;
FlakeWriter flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file, FlakeWriter flake;
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
settings);
flake.FinalSampleCount = audioSource.Length - skip_a - skip_b;
IAudioDest audioDest = flake;
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
try try
{ {
settings.Validate(); flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file,
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
settings);
flake.FinalSampleCount = audioSource.Length - skip_a - skip_b;
if (prediction_type != null) if (prediction_type != null)
flake.PredictionType = Flake.LookupPredictionType(prediction_type); flake.PredictionType = Flake.LookupPredictionType(prediction_type);
if (stereo_method != null) if (stereo_method != null)
@@ -350,18 +358,6 @@ namespace CUETools.FlakeExe
flake.OrderMethod = Flake.LookupOrderMethod(order_method); flake.OrderMethod = Flake.LookupOrderMethod(order_method);
if (window_function != null) if (window_function != null)
flake.WindowFunction = Flake.LookupWindowFunction(window_function); 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) if (min_precision >= 0)
flake.MinPrecisionSearch = min_precision; flake.MinPrecisionSearch = min_precision;
if (max_precision >= 0) if (max_precision >= 0)
@@ -382,6 +378,9 @@ namespace CUETools.FlakeExe
return 4; return 4;
} }
IAudioDest audioDest = flake;
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
if (!quiet) if (!quiet)
{ {
Console.WriteLine("Filename : {0}", input_file); Console.WriteLine("Filename : {0}", input_file);
@@ -479,12 +478,12 @@ namespace CUETools.FlakeExe
flake.StereoMethod.ToString().PadRight(15), flake.StereoMethod.ToString().PadRight(15),
(flake.OrderMethod.ToString() + "(" + flake.EstimationDepth.ToString() + ")").PadRight(15), (flake.OrderMethod.ToString() + "(" + flake.EstimationDepth.ToString() + ")").PadRight(15),
flake.WindowFunction, flake.WindowFunction,
flake.MinPartitionOrder, (flake.Settings as FlakeWriterSettings).MinPartitionOrder,
flake.MaxPartitionOrder, (flake.Settings as FlakeWriterSettings).MaxPartitionOrder,
flake.MinLPCOrder, (flake.Settings as FlakeWriterSettings).MinLPCOrder,
flake.MaxLPCOrder, (flake.Settings as FlakeWriterSettings).MaxLPCOrder,
flake.MinFixedOrder, (flake.Settings as FlakeWriterSettings).MinFixedOrder,
flake.MaxFixedOrder, (flake.Settings as FlakeWriterSettings).MaxFixedOrder,
flake.MinPrecisionSearch, flake.MinPrecisionSearch,
flake.MaxPrecisionSearch, flake.MaxPrecisionSearch,
flake.Settings.BlockSize, flake.Settings.BlockSize,

View File

@@ -67,8 +67,15 @@ namespace CUETools.Processor
var settings = encoder.settings.Clone(); var settings = encoder.settings.Clone();
settings.PCM = pcm; settings.PCM = pcm;
settings.Padding = padding; settings.Padding = padding;
settings.Validate(); object o;
object o = Activator.CreateInstance(encoder.type, path, settings); try
{
o = Activator.CreateInstance(encoder.type, path, settings);
}
catch (System.Reflection.TargetInvocationException ex)
{
throw ex.InnerException;
}
if (o == null || !(o is IAudioDest)) if (o == null || !(o is IAudioDest))
throw new Exception("Unsupported audio type: " + path + ": " + encoder.type.FullName); throw new Exception("Unsupported audio type: " + path + ": " + encoder.type.FullName);
dest = o as IAudioDest; dest = o as IAudioDest;