mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
Flake: use new window functions (partial_tukey, punchout_tukey).
This commit is contained in:
@@ -6,12 +6,14 @@
|
||||
public int* samples;
|
||||
public uint done_fixed;
|
||||
public LpcContext[] lpc_ctx;
|
||||
public LpcSubframeInfo sf;
|
||||
|
||||
public ALACSubframeInfo()
|
||||
{
|
||||
best = new ALACSubframe();
|
||||
lpc_ctx = new LpcContext[Alac.MAX_LPC_WINDOWS];
|
||||
for (int i = 0; i < Alac.MAX_LPC_WINDOWS; i++)
|
||||
sf = new LpcSubframeInfo();
|
||||
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
|
||||
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
|
||||
lpc_ctx[i] = new LpcContext();
|
||||
}
|
||||
|
||||
@@ -21,7 +23,8 @@
|
||||
best.residual = r;
|
||||
best.size = AudioSamples.UINT32_MAX;
|
||||
best.order = 0;
|
||||
for (int iWindow = 0; iWindow < Alac.MAX_LPC_WINDOWS; iWindow++)
|
||||
sf.Reset();
|
||||
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++)
|
||||
lpc_ctx[iWindow].Reset();
|
||||
done_fixed = 0;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace CUETools.Codecs.ALAC
|
||||
public class ALACWriterSettings: AudioEncoderSettings
|
||||
{
|
||||
public ALACWriterSettings()
|
||||
: base("0 1 2 3 4 5 6 7 8 9 10", "3")
|
||||
: base("0 1 2 3 4 5 6 7 8 9 10", "5")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ namespace CUETools.Codecs.ALAC
|
||||
int[] verifyBuffer;
|
||||
int[] residualBuffer;
|
||||
float[] windowBuffer;
|
||||
LpcWindowSection[,] windowSections;
|
||||
int samplesInBuffer = 0;
|
||||
|
||||
int m_blockSize = 0;
|
||||
@@ -122,7 +123,8 @@ namespace CUETools.Codecs.ALAC
|
||||
|
||||
samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (Settings.PCM.ChannelCount == 2 ? 5 : Settings.PCM.ChannelCount)];
|
||||
residualBuffer = new int[Alac.MAX_BLOCKSIZE * (Settings.PCM.ChannelCount == 2 ? 6 : Settings.PCM.ChannelCount + 1)];
|
||||
windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * Alac.MAX_LPC_WINDOWS];
|
||||
windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
|
||||
windowSections = new LpcWindowSection[lpc.MAX_LPC_WINDOWS, lpc.MAX_LPC_SECTIONS];
|
||||
|
||||
eparams.set_defaults(m_settings.EncoderModeIndex);
|
||||
|
||||
@@ -875,7 +877,11 @@ namespace CUETools.Codecs.ALAC
|
||||
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
|
||||
|
||||
lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2);
|
||||
fixed (LpcWindowSection* sections = &windowSections[iWindow, 0])
|
||||
lpc_ctx.GetReflection(
|
||||
frame.subframes[ch].sf, max_order, smp,
|
||||
frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2, sections,
|
||||
Settings.PCM.BitsPerSample * 2 + BitReader.log2i(frame.blocksize) >= 61);
|
||||
lpc_ctx.ComputeLPC(lpcs);
|
||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, min_order, max_order, 5.0, 1.0/18);
|
||||
for (i = 0; i < eparams.estimation_depth && i < max_order; i++)
|
||||
@@ -945,20 +951,36 @@ namespace CUETools.Codecs.ALAC
|
||||
{
|
||||
case WindowMethod.Estimate:
|
||||
{
|
||||
int best_window = -1;
|
||||
double best_error = 0;
|
||||
int order = 2;
|
||||
int order = 4;
|
||||
float* err = stackalloc float[lpc.MAX_LPC_ORDER];
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
frame.subframes[ch].lpc_ctx[i].GetReflection(order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + i * Alac.MAX_BLOCKSIZE * 2);
|
||||
double err = frame.subframes[ch].lpc_ctx[i].prediction_error[order - 1] / frame.subframes[ch].lpc_ctx[i].autocorr_values[0];
|
||||
if (best_window == -1 || best_error > err)
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[i];
|
||||
fixed (LpcWindowSection* sections = &windowSections[i, 0])
|
||||
lpc_ctx.GetReflection(
|
||||
frame.subframes[ch].sf, order,
|
||||
frame.subframes[ch].samples,
|
||||
frame.window_buffer + i * Alac.MAX_BLOCKSIZE * 2, sections,
|
||||
Settings.PCM.BitsPerSample * 2 + BitReader.log2i(frame.blocksize) >= 61);
|
||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, order, 4.5, 0.0);
|
||||
err[i] = (float)(lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0) - frame.blocksize * Math.Log(lpc_ctx.autocorr_values[0]) / 2);
|
||||
}
|
||||
int* best_windows = stackalloc int[lpc.MAX_LPC_ORDER];
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
best_windows[i] = i;
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
best_window = i;
|
||||
best_error = err;
|
||||
for (int j = i + 1; j < _windowcount; j++)
|
||||
{
|
||||
if (err[best_windows[i]] > err[best_windows[j]])
|
||||
{
|
||||
int tmp = best_windows[j];
|
||||
best_windows[j] = best_windows[i];
|
||||
best_windows[i] = tmp;
|
||||
}
|
||||
}
|
||||
return best_window;
|
||||
}
|
||||
return best_windows[0];
|
||||
}
|
||||
case WindowMethod.Evaluate:
|
||||
encode_residual_pass1(frame, ch, -1);
|
||||
@@ -978,10 +1000,16 @@ namespace CUETools.Codecs.ALAC
|
||||
case StereoMethod.Estimate:
|
||||
for (int ch = 0; ch < subframes; ch++)
|
||||
{
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0];
|
||||
int iWindow = 0;
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
|
||||
int stereo_order = Math.Min(8, eparams.max_prediction_order);
|
||||
double alpha = 1.5; // 4.5 + eparams.max_prediction_order / 10.0;
|
||||
lpc_ctx.GetReflection(stereo_order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer);
|
||||
fixed (LpcWindowSection* sections = &windowSections[iWindow, 0])
|
||||
lpc_ctx.GetReflection(
|
||||
frame.subframes[ch].sf, stereo_order,
|
||||
frame.subframes[ch].samples,
|
||||
frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2, sections,
|
||||
Settings.PCM.BitsPerSample * 2 + BitReader.log2i(frame.blocksize) >= 61);
|
||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, stereo_order, alpha, 0);
|
||||
frame.subframes[ch].best.size = (uint)Math.Max(0, lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], alpha, 0));
|
||||
}
|
||||
@@ -1060,13 +1088,17 @@ namespace CUETools.Codecs.ALAC
|
||||
|
||||
unsafe void calculate_window(float * window, window_function func, WindowFunction flag)
|
||||
{
|
||||
if ((eparams.window_function & flag) == 0 || _windowcount == Alac.MAX_LPC_WINDOWS)
|
||||
if ((eparams.window_function & flag) == 0 || _windowcount == lpc.MAX_LPC_WINDOWS)
|
||||
return;
|
||||
int sz = _windowsize;
|
||||
float* pos = window + _windowcount * Alac.MAX_BLOCKSIZE * 2;
|
||||
do
|
||||
{
|
||||
windowSections[_windowcount, 0].setData(0, sz);
|
||||
for (int j = 1; j < lpc.MAX_LPC_SECTIONS; j++)
|
||||
windowSections[_windowcount, j].setZero(sz, sz);
|
||||
func(pos, sz);
|
||||
break;
|
||||
if ((sz & 1) != 0)
|
||||
break;
|
||||
pos += sz;
|
||||
@@ -1091,8 +1123,32 @@ namespace CUETools.Codecs.ALAC
|
||||
calculate_window(window, lpc.window_tukey, WindowFunction.Tukey);
|
||||
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
|
||||
calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
|
||||
int tukey_parts = 2;
|
||||
double overlap = -0.3;
|
||||
double overlap_units = overlap / (1.0 - overlap);
|
||||
for (int m = 0; m < tukey_parts; m++)
|
||||
calculate_window(window, (w, wsz) =>
|
||||
{
|
||||
lpc.window_punchout_tukey(w, wsz, 0.1,
|
||||
m / (tukey_parts + overlap_units),
|
||||
(m + 1 + overlap_units) / (tukey_parts + overlap_units));
|
||||
}, WindowFunction.PartialTukey);
|
||||
|
||||
tukey_parts = 3;
|
||||
overlap = -0.1;
|
||||
//overlap = 0.1;
|
||||
overlap_units = overlap / (1.0 - overlap);
|
||||
for (int m = 0; m < tukey_parts; m++)
|
||||
calculate_window(window, (w, wsz) =>
|
||||
{
|
||||
lpc.window_punchout_tukey(w, wsz, 0.1,
|
||||
m / (tukey_parts + overlap_units),
|
||||
(m + 1 + overlap_units) / (tukey_parts + overlap_units));
|
||||
}, WindowFunction.PunchoutTukey);
|
||||
if (_windowcount == 0)
|
||||
throw new Exception("invalid windowfunction");
|
||||
fixed (LpcWindowSection* sections = &windowSections[0, 0])
|
||||
LpcWindowSection.Detect(_windowcount, window, Alac.MAX_BLOCKSIZE * 2, _windowsize, sections);
|
||||
}
|
||||
frame.window_buffer = window;
|
||||
|
||||
@@ -1793,11 +1849,13 @@ namespace CUETools.Codecs.ALAC
|
||||
case 4:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.PartialTukey | WindowFunction.PunchoutTukey;
|
||||
max_prediction_order = 8;
|
||||
break;
|
||||
case 5:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.PartialTukey | WindowFunction.PunchoutTukey;
|
||||
break;
|
||||
case 6:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace CUETools.Codecs.ALAC
|
||||
public const int MAX_RICE_PARAM = 14;
|
||||
public const int MAX_PARTITION_ORDER = 8;
|
||||
public const int MAX_PARTITIONS = 1 << MAX_PARTITION_ORDER;
|
||||
public const int MAX_LPC_WINDOWS = 4;
|
||||
|
||||
public const uint UINT32_MAX = 0xffffffff;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
Hann = 4,
|
||||
Flattop = 8,
|
||||
Bartlett = 16,
|
||||
TukFlat = 10
|
||||
TukFlat = 10,
|
||||
PartialTukey = 32,
|
||||
PunchoutTukey = 64,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +270,8 @@ namespace CUETools.Codecs.FLACCL
|
||||
string _path;
|
||||
long _position;
|
||||
|
||||
public const int MAX_LPC_WINDOWS = 2;
|
||||
|
||||
// number of audio channels
|
||||
// valid values are 1 to 8
|
||||
int channels, ch_code;
|
||||
@@ -1090,7 +1092,7 @@ namespace CUETools.Codecs.FLACCL
|
||||
|
||||
unsafe void calculate_window(FLACCLTask task, window_function func, WindowFunction flag)
|
||||
{
|
||||
if ((eparams.window_function & flag) == 0 || task.nWindowFunctions == lpc.MAX_LPC_WINDOWS)
|
||||
if ((eparams.window_function & flag) == 0 || task.nWindowFunctions == MAX_LPC_WINDOWS)
|
||||
return;
|
||||
|
||||
func(((float*)task.clWindowFunctionsPtr) + task.nWindowFunctions * task.frameSize, task.frameSize);
|
||||
@@ -2508,10 +2510,10 @@ namespace CUETools.Codecs.FLACCL
|
||||
int residualBufferLen = sizeof(int) * MAX_CHANNELSIZE * channels; // need to adjust residualOffset?
|
||||
int partitionsLen = sizeof(int) * ((writer.Settings.PCM.BitsPerSample > 16 ? 31 : 15) * 2 << 8) * channels * MAX_FRAMES;
|
||||
int riceParamsLen = sizeof(int) * (4 << 8) * channels * MAX_FRAMES;
|
||||
int autocorLen = sizeof(float) * (MAX_ORDER + 1) * lpc.MAX_LPC_WINDOWS * channelsCount * MAX_FRAMES;
|
||||
int autocorLen = sizeof(float) * (MAX_ORDER + 1) * FLACCLWriter.MAX_LPC_WINDOWS * channelsCount * MAX_FRAMES;
|
||||
int lpcDataLen = autocorLen * 32;
|
||||
int resOutLen = sizeof(int) * channelsCount * (lpc.MAX_LPC_WINDOWS * lpc.MAX_LPC_ORDER + 8) * MAX_FRAMES;
|
||||
int wndLen = sizeof(float) * MAX_CHANNELSIZE /** 2*/ * lpc.MAX_LPC_WINDOWS;
|
||||
int resOutLen = sizeof(int) * channelsCount * (FLACCLWriter.MAX_LPC_WINDOWS * lpc.MAX_LPC_ORDER + 8) * MAX_FRAMES;
|
||||
int wndLen = sizeof(float) * MAX_CHANNELSIZE /** 2*/ * FLACCLWriter.MAX_LPC_WINDOWS;
|
||||
int selectedLen = sizeof(int) * 32 * channelsCount * MAX_FRAMES;
|
||||
int riceLen = sizeof(int) * channels * MAX_CHANNELSIZE;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
public int frame_number;
|
||||
public FlacSubframe current;
|
||||
public float* window_buffer;
|
||||
public int nSeg = 0;
|
||||
|
||||
public BitWriter writer = null;
|
||||
public int writer_offset = 0;
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace CUETools.Codecs.FLAKE
|
||||
public FlacSubframeInfo()
|
||||
{
|
||||
best = new FlacSubframe();
|
||||
sf = new LpcSubframeInfo();
|
||||
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
|
||||
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
|
||||
lpc_ctx[i] = new LpcContext();
|
||||
@@ -22,8 +23,10 @@ namespace CUETools.Codecs.FLAKE
|
||||
best.residual = r;
|
||||
best.type = SubframeType.Verbatim;
|
||||
best.size = AudioSamples.UINT32_MAX;
|
||||
sf.Reset();
|
||||
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++)
|
||||
lpc_ctx[iWindow].Reset();
|
||||
//sf.obits = obits;
|
||||
done_fixed = 0;
|
||||
}
|
||||
|
||||
@@ -33,5 +36,6 @@ namespace CUETools.Codecs.FLAKE
|
||||
public int* samples;
|
||||
public uint done_fixed;
|
||||
public LpcContext[] lpc_ctx;
|
||||
public LpcSubframeInfo sf;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#define NOINTEROP
|
||||
#define VARIANT1
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
@@ -84,14 +85,14 @@ namespace CUETools.Codecs.FLAKE
|
||||
}
|
||||
|
||||
[DefaultValue(-1)]
|
||||
[DefaultValueForMode(3, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0)]
|
||||
[DefaultValueForMode(2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0)]
|
||||
[Browsable(false)]
|
||||
[DisplayName("MinFixedOrder")]
|
||||
[SRDescription(typeof(Properties.Resources), "MinFixedOrderDescription")]
|
||||
public int MinFixedOrder { get; set; }
|
||||
|
||||
[DefaultValue(-1)]
|
||||
[DefaultValueForMode(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4)]
|
||||
[DefaultValueForMode(2, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4)]
|
||||
[Browsable(false)]
|
||||
[DisplayName("MaxFixedOrder")]
|
||||
[SRDescription(typeof(Properties.Resources), "MaxFixedOrderDescription")]
|
||||
@@ -104,7 +105,7 @@ namespace CUETools.Codecs.FLAKE
|
||||
public int MinLPCOrder { get; set; }
|
||||
|
||||
[DefaultValue(-1)]
|
||||
[DefaultValueForMode(6, 8, 12, 8, 12, 12, 12, 12, 12, 32, 32, 32)]
|
||||
[DefaultValueForMode(8, 8, 8, 12, 12, 12, 12, 12, 12, 32, 32, 32)]
|
||||
[Browsable(false)]
|
||||
[DisplayName("MaxLPCOrder")]
|
||||
[SRDescription(typeof(Properties.Resources), "MaxLPCOrderDescription")]
|
||||
@@ -117,7 +118,7 @@ namespace CUETools.Codecs.FLAKE
|
||||
public int MinPartitionOrder { get; set; }
|
||||
|
||||
[DefaultValue(-1)]
|
||||
[DefaultValueForMode(6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8)]
|
||||
[DefaultValueForMode(6, 8, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8)]
|
||||
[DisplayName("MaxPartitionOrder")]
|
||||
[Browsable(false)]
|
||||
[SRDescription(typeof(Properties.Resources), "MaxPartitionOrderDescription")]
|
||||
@@ -192,6 +193,9 @@ namespace CUETools.Codecs.FLAKE
|
||||
int[] residualBuffer;
|
||||
float[] windowBuffer;
|
||||
double[] windowScale;
|
||||
LpcWindowSection[, ,] windowSections;
|
||||
|
||||
WindowFunction[] windowType;
|
||||
int samplesInBuffer = 0;
|
||||
|
||||
int m_blockSize = 0;
|
||||
@@ -230,6 +234,8 @@ namespace CUETools.Codecs.FLAKE
|
||||
residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)];
|
||||
windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
|
||||
windowScale = new double[lpc.MAX_LPC_WINDOWS];
|
||||
windowType = new WindowFunction[lpc.MAX_LPC_WINDOWS];
|
||||
windowSections = new LpcWindowSection[12, lpc.MAX_LPC_WINDOWS, lpc.MAX_LPC_SECTIONS];
|
||||
|
||||
eparams.flake_set_defaults(m_settings);
|
||||
|
||||
@@ -526,57 +532,291 @@ namespace CUETools.Codecs.FLAKE
|
||||
|
||||
unsafe static void encode_residual_fixed(int* res, int* smp, int n, int order)
|
||||
{
|
||||
int i;
|
||||
int s0, s1, s2;
|
||||
switch (order)
|
||||
int next_error_0, next_error_1, next_error_2, next_error_3, next_error_4;
|
||||
int last_error_0, last_error_1, last_error_2, last_error_3;
|
||||
int* end = smp + n;
|
||||
|
||||
if (order == 0)
|
||||
{
|
||||
case 0:
|
||||
AudioSamples.MemCpy(res, smp, n);
|
||||
return;
|
||||
case 1:
|
||||
*(res++) = s1 = *(smp++);
|
||||
for (i = n - 1; i > 0; i--)
|
||||
{
|
||||
s0 = *(smp++);
|
||||
*(res++) = s0 - s1;
|
||||
s1 = s0;
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
*(res++) = s2 = *(smp++);
|
||||
*(res++) = s1 = *(smp++);
|
||||
for (i = n - 2; i > 0; i--)
|
||||
{
|
||||
s0 = *(smp++);
|
||||
*(res++) = s0 - 2 * s1 + s2;
|
||||
s2 = s1;
|
||||
s1 = s0;
|
||||
}
|
||||
return;
|
||||
case 3:
|
||||
res[0] = smp[0];
|
||||
res[1] = smp[1];
|
||||
res[2] = smp[2];
|
||||
for (i = 3; i < n; i++)
|
||||
{
|
||||
res[i] = smp[i] - 3 * smp[i - 1] + 3 * smp[i - 2] - smp[i - 3];
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
res[0] = smp[0];
|
||||
res[1] = smp[1];
|
||||
res[2] = smp[2];
|
||||
res[3] = smp[3];
|
||||
for (i = 4; i < n; i++)
|
||||
{
|
||||
res[i] = smp[i] - 4 * smp[i - 1] + 6 * smp[i - 2] - 4 * smp[i - 3] + smp[i - 4];
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
last_error_0 = next_error_0;
|
||||
|
||||
if (order == 1)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
#if VARIANT1
|
||||
int error, save;
|
||||
error = *(smp++); save = error;
|
||||
error -= last_error_0; *(res++) = error; last_error_0 = save;
|
||||
#else
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
|
||||
*(res++) = (int)next_error_1;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
|
||||
if (order == 2)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
#if VARIANT1
|
||||
int error, save;
|
||||
error = *(smp++); save = error;
|
||||
error -= last_error_0; last_error_0 = save; save = error;
|
||||
error -= last_error_1; *(res++) = error; last_error_1 = save;
|
||||
#else
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
|
||||
*(res++) = (int)next_error_2;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
|
||||
if (order == 3)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
#if VARIANT1
|
||||
int error, save;
|
||||
error = *(smp++); save = error;
|
||||
error -= last_error_0; last_error_0 = save; save = error;
|
||||
error -= last_error_1; last_error_1 = save; save = error;
|
||||
error -= last_error_2; *(res++) = error; last_error_2 = save;
|
||||
#else
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
next_error_3 = next_error_2 - last_error_2;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
|
||||
*(res++) = (int)next_error_3;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
next_error_3 = next_error_2 - last_error_2;
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
last_error_3 = next_error_3;
|
||||
|
||||
if (order == 4)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
#if VARIANT1
|
||||
int error, save;
|
||||
error = *(smp++); save = error;
|
||||
error -= last_error_0; last_error_0 = save; save = error;
|
||||
error -= last_error_1; last_error_1 = save; save = error;
|
||||
error -= last_error_2; last_error_2 = save; save = error;
|
||||
error -= last_error_3; *(res++) = error; last_error_3 = save;
|
||||
#else
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
next_error_3 = next_error_2 - last_error_2;
|
||||
next_error_4 = next_error_3 - last_error_3;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
last_error_3 = next_error_3;
|
||||
|
||||
*(res++) = (int)next_error_4;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
#if XXX
|
||||
unsafe static int encode_residual_fixed_estimate_best_order(int* res, int* smp, int n, int order)
|
||||
{
|
||||
int next_error_0, next_error_1, next_error_2, next_error_3, next_error_4;
|
||||
int last_error_0, last_error_1, last_error_2, last_error_3;
|
||||
int* end = smp + n;
|
||||
ulong total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
|
||||
|
||||
if (order == 0)
|
||||
{
|
||||
AudioSamples.MemCpy(res, smp, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
last_error_0 = next_error_0;
|
||||
|
||||
if (order == 1)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
|
||||
total_error_0 += (ulong)((next_error_0 << 1) ^ (next_error_0 >> 31));
|
||||
total_error_1 += (ulong)((next_error_1 << 1) ^ (next_error_1 >> 31));
|
||||
|
||||
*(res++) = (int)next_error_1;
|
||||
}
|
||||
|
||||
if ((total_error_0 < total_error_1))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
|
||||
if (order == 2)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
|
||||
total_error_0 += (ulong)((next_error_0 << 1) ^ (next_error_0 >> 31));
|
||||
total_error_1 += (ulong)((next_error_1 << 1) ^ (next_error_1 >> 31));
|
||||
total_error_2 += (ulong)((next_error_2 << 1) ^ (next_error_2 >> 31));
|
||||
|
||||
*(res++) = (int)next_error_2;
|
||||
}
|
||||
|
||||
if ((total_error_0 < total_error_1) & (total_error_0 < total_error_2))
|
||||
return 0;
|
||||
else if ((total_error_1 < total_error_2))
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
|
||||
if (order == 3)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
next_error_3 = next_error_2 - last_error_2;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
|
||||
total_error_0 += (ulong)((next_error_0 << 1) ^ (next_error_0 >> 31));
|
||||
total_error_1 += (ulong)((next_error_1 << 1) ^ (next_error_1 >> 31));
|
||||
total_error_2 += (ulong)((next_error_2 << 1) ^ (next_error_2 >> 31));
|
||||
total_error_3 += (ulong)((next_error_3 << 1) ^ (next_error_3 >> 31));
|
||||
|
||||
*(res++) = (int)next_error_3;
|
||||
}
|
||||
|
||||
if ((total_error_0 < total_error_1) & (total_error_0 < total_error_2) & (total_error_0 < total_error_3))
|
||||
return 0;
|
||||
else if ((total_error_1 < total_error_2) & (total_error_1 < total_error_3))
|
||||
return 1;
|
||||
else if ((total_error_2 < total_error_3))
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
next_error_0 = *(res++) = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
next_error_3 = next_error_2 - last_error_2;
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
last_error_3 = next_error_3;
|
||||
|
||||
if (order == 4)
|
||||
{
|
||||
while (smp < end)
|
||||
{
|
||||
next_error_0 = *(smp++);
|
||||
next_error_1 = next_error_0 - last_error_0;
|
||||
next_error_2 = next_error_1 - last_error_1;
|
||||
next_error_3 = next_error_2 - last_error_2;
|
||||
next_error_4 = next_error_3 - last_error_3;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
last_error_3 = next_error_3;
|
||||
|
||||
total_error_0 += (ulong)((next_error_0 << 1) ^ (next_error_0 >> 31));
|
||||
total_error_1 += (ulong)((next_error_1 << 1) ^ (next_error_1 >> 31));
|
||||
total_error_2 += (ulong)((next_error_2 << 1) ^ (next_error_2 >> 31));
|
||||
total_error_3 += (ulong)((next_error_3 << 1) ^ (next_error_3 >> 31));
|
||||
total_error_4 += (ulong)((next_error_4 << 1) ^ (next_error_4 >> 31));
|
||||
|
||||
*(res++) = (int)next_error_4;
|
||||
}
|
||||
|
||||
if ((total_error_0 < total_error_1) & (total_error_0 < total_error_2) & (total_error_0 < total_error_3) & (total_error_0 < total_error_4))
|
||||
return 0;
|
||||
else if ((total_error_1 < total_error_2) & (total_error_1 < total_error_3) & (total_error_1 < total_error_4))
|
||||
return 1;
|
||||
else if ((total_error_2 < total_error_3) & (total_error_2 < total_error_4))
|
||||
return 2;
|
||||
else if (total_error_3 < total_error_4)
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
#endif
|
||||
static unsafe uint calc_optimal_rice_params(int porder, int* parm, ulong* sums, uint n, uint pred_order, ref int method)
|
||||
{
|
||||
uint part = (1U << porder);
|
||||
@@ -1079,6 +1319,21 @@ new int[] { // 30
|
||||
frame.current.order = order;
|
||||
frame.current.type = SubframeType.Fixed;
|
||||
|
||||
#if XXX
|
||||
int best_order = order;
|
||||
if (frame.subframes[ch].done_fixed == 0)
|
||||
{
|
||||
best_order = encode_residual_fixed_estimate_best_order(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order);
|
||||
if (best_order != order)
|
||||
{
|
||||
//frame.subframes[ch].done_fixed |= (1U << order);
|
||||
order = best_order;
|
||||
frame.current.order = order;
|
||||
encode_residual_fixed(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
encode_residual_fixed(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order);
|
||||
|
||||
int pmax = get_max_p_order(m_settings.MaxPartitionOrder, frame.blocksize, frame.current.order);
|
||||
@@ -1091,7 +1346,78 @@ new int[] { // 30
|
||||
frame.ChooseBestSubframe(ch);
|
||||
}
|
||||
|
||||
unsafe void encode_residual(FlacFrame frame, int ch, PredictionType predict, OrderMethod omethod, int pass, int best_window)
|
||||
unsafe void fixed_compute_best_predictor(int* data, uint data_len, ulong* errors)//, float* residual_bits_per_sample)
|
||||
{
|
||||
long last_error_0 = data[-1];
|
||||
long last_error_1 = data[-1] - data[-2];
|
||||
long last_error_2 = last_error_1 - (data[-2] - data[-3]);
|
||||
long last_error_3 = last_error_2 - (data[-2] - 2 * data[-3] + data[-4]);
|
||||
ulong total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
|
||||
|
||||
#if VARIANT1
|
||||
long error, save;
|
||||
int* finish = data + data_len;
|
||||
while (data < finish)
|
||||
{
|
||||
error = *(data++); total_error_0 += (ulong)((error << 1) ^ (error >> 63)); save = error;
|
||||
error -= last_error_0; total_error_1 += (ulong)((error << 1) ^ (error >> 63)); last_error_0 = save; save = error;
|
||||
error -= last_error_1; total_error_2 += (ulong)((error << 1) ^ (error >> 63)); last_error_1 = save; save = error;
|
||||
error -= last_error_2; total_error_3 += (ulong)((error << 1) ^ (error >> 63)); last_error_2 = save; save = error;
|
||||
error -= last_error_3; total_error_4 += (ulong)((error << 1) ^ (error >> 63)); last_error_3 = save;
|
||||
}
|
||||
#else
|
||||
int* finish = data + data_len;
|
||||
while (data < finish)
|
||||
{
|
||||
long next_error_0 = *(data++);
|
||||
long next_error_1 = next_error_0 - last_error_0;
|
||||
long next_error_2 = next_error_1 - last_error_1;
|
||||
long next_error_3 = next_error_2 - last_error_2;
|
||||
long next_error_4 = next_error_3 - last_error_3;
|
||||
|
||||
last_error_0 = next_error_0;
|
||||
last_error_1 = next_error_1;
|
||||
last_error_2 = next_error_2;
|
||||
last_error_3 = next_error_3;
|
||||
|
||||
total_error_0 += (ulong)((last_error_0 << 1) ^ (last_error_0 >> 63));
|
||||
total_error_1 += (ulong)((last_error_1 << 1) ^ (last_error_1 >> 63));
|
||||
total_error_2 += (ulong)((last_error_2 << 1) ^ (last_error_2 >> 63));
|
||||
total_error_3 += (ulong)((last_error_3 << 1) ^ (last_error_3 >> 63));
|
||||
total_error_4 += (ulong)((next_error_4 << 1) ^ (next_error_4 >> 63));
|
||||
}
|
||||
#endif
|
||||
|
||||
errors[0] = total_error_0;
|
||||
errors[1] = total_error_1;
|
||||
errors[2] = total_error_2;
|
||||
errors[3] = total_error_3;
|
||||
errors[4] = total_error_4;
|
||||
|
||||
//residual_bits_per_sample[0] = (float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
//residual_bits_per_sample[1] = (float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
//residual_bits_per_sample[2] = (float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
//residual_bits_per_sample[3] = (float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
//residual_bits_per_sample[4] = (float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
}
|
||||
|
||||
unsafe int fixed_compute_best_predictor_order(ulong* error)
|
||||
{
|
||||
int order;
|
||||
if ((error[0] < error[1]) & (error[0] < error[2]) & (error[0] < error[3]) & (error[0] < error[4]))
|
||||
order = 0;
|
||||
else if ((error[1] < error[2]) & (error[1] < error[3]) & (error[1] < error[4]))
|
||||
order = 1;
|
||||
else if ((error[2] < error[3]) & (error[2] < error[4]))
|
||||
order = 2;
|
||||
else if (error[3] < error[4])
|
||||
order = 3;
|
||||
else
|
||||
order = 4;
|
||||
return order;
|
||||
}
|
||||
|
||||
unsafe void encode_residual(FlacFrame frame, int ch, PredictionType predict, OrderMethod omethod, int pass, int windows_mask)
|
||||
{
|
||||
int* smp = frame.subframes[ch].samples;
|
||||
int i, n = frame.blocksize;
|
||||
@@ -1132,12 +1458,14 @@ new int[] { // 30
|
||||
|
||||
for (int iWindow = 0; iWindow < _windowcount; iWindow++)
|
||||
{
|
||||
if (best_window != -1 && iWindow != best_window)
|
||||
if ((windows_mask & (1 << iWindow)) == 0)
|
||||
continue;
|
||||
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
|
||||
|
||||
lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2);
|
||||
fixed (LpcWindowSection* sections = &windowSections[frame.nSeg, iWindow, 0])
|
||||
lpc_ctx.GetReflection(
|
||||
frame.subframes[ch].sf, max_order, smp, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2, sections,
|
||||
frame.subframes[ch].obits * 2 + BitReader.log2i(frame.blocksize) >= 61);
|
||||
lpc_ctx.ComputeLPC(lpcs);
|
||||
|
||||
//int frameSize = n;
|
||||
@@ -1217,9 +1545,22 @@ new int[] { // 30
|
||||
int max_fixed_order = Math.Min(m_settings.MaxFixedOrder, 4);
|
||||
int min_fixed_order = Math.Min(m_settings.MinFixedOrder, max_fixed_order);
|
||||
|
||||
for (i = min_fixed_order; i <= max_fixed_order; i++)
|
||||
if (min_fixed_order == 0 && max_fixed_order == 4)
|
||||
{
|
||||
if (frame.subframes[ch].done_fixed == 0)
|
||||
{
|
||||
ulong* fixed_errors = stackalloc ulong[5];
|
||||
fixed_compute_best_predictor(smp + 4, (uint)n - 4, fixed_errors);
|
||||
i = fixed_compute_best_predictor_order(fixed_errors);
|
||||
encode_residual_fixed_sub(frame, i, ch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = max_fixed_order; i >= min_fixed_order; i--)
|
||||
encode_residual_fixed_sub(frame, i, ch);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1379,25 +1720,25 @@ new int[] { // 30
|
||||
bitwriter.flush();
|
||||
}
|
||||
|
||||
unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window)
|
||||
unsafe void encode_residual_pass1(FlacFrame frame, int ch, int windows_mask)
|
||||
{
|
||||
int max_prediction_order = m_settings.MaxLPCOrder;
|
||||
int max_fixed_order = m_settings.MaxFixedOrder;
|
||||
int min_fixed_order = m_settings.MinFixedOrder;
|
||||
//int max_fixed_order = m_settings.MaxFixedOrder;
|
||||
//int min_fixed_order = m_settings.MinFixedOrder;
|
||||
int lpc_min_precision_search = eparams.lpc_min_precision_search;
|
||||
int lpc_max_precision_search = eparams.lpc_max_precision_search;
|
||||
int max_partition_order = m_settings.MaxPartitionOrder;
|
||||
int estimation_depth = eparams.estimation_depth;
|
||||
var development_mode = eparams.development_mode;
|
||||
m_settings.MinFixedOrder = 2;
|
||||
m_settings.MaxFixedOrder = 2;
|
||||
//m_settings.MinFixedOrder = 2;
|
||||
//m_settings.MaxFixedOrder = 2;
|
||||
eparams.lpc_min_precision_search = eparams.lpc_max_precision_search;
|
||||
m_settings.MaxLPCOrder = Math.Min(m_settings.MaxLPCOrder, Math.Max(m_settings.MinLPCOrder, 8));
|
||||
eparams.estimation_depth = 1;
|
||||
eparams.development_mode = Math.Min(eparams.development_mode, -1);
|
||||
encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window);
|
||||
m_settings.MinFixedOrder = min_fixed_order;
|
||||
m_settings.MaxFixedOrder = max_fixed_order;
|
||||
encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, windows_mask);
|
||||
//m_settings.MinFixedOrder = min_fixed_order;
|
||||
//m_settings.MaxFixedOrder = max_fixed_order;
|
||||
m_settings.MaxLPCOrder = max_prediction_order;
|
||||
eparams.lpc_min_precision_search = lpc_min_precision_search;
|
||||
eparams.lpc_max_precision_search = lpc_max_precision_search;
|
||||
@@ -1408,36 +1749,140 @@ new int[] { // 30
|
||||
|
||||
unsafe void encode_residual_pass2(FlacFrame frame, int ch)
|
||||
{
|
||||
encode_residual(frame, ch, eparams.prediction_type, eparams.order_method, 2, estimate_best_window(frame, ch));
|
||||
encode_residual(frame, ch, eparams.prediction_type, eparams.order_method, 2, estimate_best_windows(frame, ch));
|
||||
}
|
||||
|
||||
unsafe int estimate_best_window(FlacFrame frame, int ch)
|
||||
unsafe int estimate_best_windows_akaike(FlacFrame frame, int ch, int count, bool onePerType)
|
||||
{
|
||||
if (_windowcount == 1)
|
||||
return 0;
|
||||
int* windows_present = stackalloc int[_windowcount];
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
windows_present[i] = 0;
|
||||
if (onePerType)
|
||||
{
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
for (int j = 0; j < _windowcount; j++)
|
||||
if (windowType[j] == windowType[i])
|
||||
windows_present[j]++;
|
||||
}
|
||||
|
||||
float* err = stackalloc float[lpc.MAX_LPC_ORDER];
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[i];
|
||||
if (onePerType && windows_present[i] <= count)
|
||||
{
|
||||
err[i] = 0;
|
||||
continue;
|
||||
}
|
||||
int estimate_order = 4;
|
||||
fixed (LpcWindowSection* sections = &windowSections[frame.nSeg, i, 0])
|
||||
lpc_ctx.GetReflection(
|
||||
frame.subframes[ch].sf, estimate_order,
|
||||
frame.subframes[ch].samples, frame.window_buffer + i * Flake.MAX_BLOCKSIZE * 2, sections,
|
||||
frame.subframes[ch].obits * 2 + BitReader.log2i(frame.blocksize) >= 61);
|
||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, estimate_order, 4.5, 0.0);
|
||||
//err[i] = (float)(lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0));
|
||||
//err[i] = (float)((frame.blocksize * lpc_ctx.prediction_error[lpc_ctx.best_orders[0] - 1] / windowScale[i]) + lpc_ctx.best_orders[0] * 4.5);
|
||||
//err[i] = (float)((frame.blocksize * lpc_ctx.prediction_error[lpc_ctx.best_orders[0] - 1] / windowScale[i]) + lpc_ctx.best_orders[0] * frame.subframes[ch].obits);
|
||||
|
||||
// realistic
|
||||
//err[i] = (float)(frame.blocksize * Math.Log(lpc_ctx.prediction_error[lpc_ctx.best_orders[0] - 1]) / Math.Log(2) / 2.5
|
||||
//- windowScale[i] / 2 + lpc_ctx.best_orders[0] * frame.subframes[ch].obits / 2);
|
||||
|
||||
//err[i] = (float)(frame.blocksize * Math.Log(lpc_ctx.prediction_error[lpc_ctx.best_orders[0] - 1]) / Math.Log(2) / 2.5
|
||||
//- frame.blocksize * Math.Log(lpc_ctx.autocorr_values[0]) / 2.1
|
||||
//+ Math.Log(frame.blocksize) * lpc_ctx.best_orders[0] * 4.5 / 2.5 / Math.Log(2));
|
||||
|
||||
// Akaike
|
||||
//err[i] = (float)(frame.blocksize * (Math.Log(lpc_ctx.prediction_error[lpc_ctx.best_orders[0] - 1])) + Math.Log(frame.blocksize) * lpc_ctx.best_orders[0] * 4.5);
|
||||
|
||||
//err[i] = (float)(lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0) - frame.blocksize * (frame.subframes[ch].obits + Math.Log(windowScale[i] / frame.blocksize) / 2));
|
||||
|
||||
// tested good
|
||||
err[i] = (float)(lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0) - frame.blocksize * Math.Log(lpc_ctx.autocorr_values[0]) / 2);
|
||||
}
|
||||
int* best_windows = stackalloc int[lpc.MAX_LPC_ORDER];
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
best_windows[i] = i;
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
for (int j = i + 1; j < _windowcount; j++)
|
||||
{
|
||||
if (err[best_windows[i]] > err[best_windows[j]])
|
||||
{
|
||||
int tmp = best_windows[j];
|
||||
best_windows[j] = best_windows[i];
|
||||
best_windows[i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
int window_mask = 0;
|
||||
if (onePerType)
|
||||
{
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
windows_present[i] = count;
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
int w = best_windows[i];
|
||||
if (windows_present[w] > 0)
|
||||
{
|
||||
for (int j = 0; j < _windowcount; j++)
|
||||
if (windowType[j] == windowType[w])
|
||||
windows_present[j]--;
|
||||
window_mask |= 1 << w;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < _windowcount && i < count; i++)
|
||||
window_mask |= 1 << best_windows[i];
|
||||
}
|
||||
return window_mask;
|
||||
}
|
||||
|
||||
unsafe int estimate_best_windows(FlacFrame frame, int ch)
|
||||
{
|
||||
if (_windowcount == 1 || eparams.prediction_type == PredictionType.Fixed)
|
||||
return 1;
|
||||
switch (eparams.window_method)
|
||||
{
|
||||
case WindowMethod.Estimate:
|
||||
return estimate_best_windows_akaike(frame, ch, 1, false);
|
||||
case WindowMethod.Estimate2:
|
||||
return estimate_best_windows_akaike(frame, ch, 2, false);
|
||||
case WindowMethod.Estimate3:
|
||||
return estimate_best_windows_akaike(frame, ch, 3, false);
|
||||
case WindowMethod.EstimateN:
|
||||
return estimate_best_windows_akaike(frame, ch, 1, true);
|
||||
case WindowMethod.Evaluate2:
|
||||
encode_residual_pass1(frame, ch, estimate_best_windows_akaike(frame, ch, 2, false));
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? 1 << frame.subframes[ch].best.window : 0;
|
||||
case WindowMethod.Evaluate3:
|
||||
encode_residual_pass1(frame, ch, estimate_best_windows_akaike(frame, ch, 3, false));
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? 1 << frame.subframes[ch].best.window : 0;
|
||||
case WindowMethod.EvaluateN:
|
||||
encode_residual_pass1(frame, ch, estimate_best_windows_akaike(frame, ch, 1, true));
|
||||
#if XXX
|
||||
if (frame.subframes[ch].best.type == SubframeType.LPC && frame.subframes[ch].best.order <= 4)
|
||||
{
|
||||
int best_window = -1;
|
||||
double best_error = 0;
|
||||
int order = 2;
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
frame.subframes[ch].lpc_ctx[i].GetReflection(order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + i * Flake.MAX_BLOCKSIZE * 2);
|
||||
double err = frame.subframes[ch].lpc_ctx[i].prediction_error[order - 1] / frame.subframes[ch].lpc_ctx[i].autocorr_values[0];
|
||||
//double err = frame.subframes[ch].lpc_ctx[i].autocorr_values[0] / frame.subframes[ch].lpc_ctx[i].autocorr_values[2];
|
||||
if (best_window == -1 || best_error > err)
|
||||
{
|
||||
best_window = i;
|
||||
best_error = err;
|
||||
}
|
||||
}
|
||||
return best_window;
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[frame.subframes[ch].best.window];
|
||||
double err = lpc_ctx.prediction_error[frame.subframes[ch].best.order - 1] / lpc_ctx.autocorr_values[0];
|
||||
double est = frame.blocksize * (frame.subframes[ch].obits * (1 - err));
|
||||
double est1 = frame.blocksize * (frame.subframes[ch].obits * (err));
|
||||
if (est < 0 || est1 < 0) return -1;
|
||||
}
|
||||
#endif
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? 1 << frame.subframes[ch].best.window : 0;
|
||||
case WindowMethod.Evaluate2N:
|
||||
encode_residual_pass1(frame, ch, estimate_best_windows_akaike(frame, ch, 2, true));
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? 1 << frame.subframes[ch].best.window : 0;
|
||||
case WindowMethod.Evaluate3N:
|
||||
encode_residual_pass1(frame, ch, estimate_best_windows_akaike(frame, ch, 3, true));
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? 1 << frame.subframes[ch].best.window : 0;
|
||||
case WindowMethod.Evaluate:
|
||||
encode_residual_pass1(frame, ch, -1);
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? frame.subframes[ch].best.window : -1;
|
||||
return frame.subframes[ch].best.type == SubframeType.LPC ? 1 << frame.subframes[ch].best.window : 0;
|
||||
case WindowMethod.Search:
|
||||
return -1;
|
||||
}
|
||||
@@ -1453,15 +1898,33 @@ new int[] { // 30
|
||||
case StereoMethod.Estimate:
|
||||
for (int ch = 0; ch < subframes; ch++)
|
||||
{
|
||||
#if XXX
|
||||
ulong* fixed_errors = stackalloc ulong[5];
|
||||
fixed_compute_best_predictor(frame.subframes[ch].samples + 4, (uint)frame.blocksize - 4, fixed_errors);
|
||||
int best_order = fixed_compute_best_predictor_order(fixed_errors);
|
||||
//residual_bits_per_sample[0] = (float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
frame.subframes[ch].best.size = (uint)fixed_errors[best_order];
|
||||
#else
|
||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0];
|
||||
lpc_ctx.GetReflection(4, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer);
|
||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 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 * m_settings.MaxLPCOrder);
|
||||
int estimate_order = 4;
|
||||
int iWindow = 0;
|
||||
fixed (LpcWindowSection* sections = &windowSections[frame.nSeg, iWindow, 0])
|
||||
lpc_ctx.GetReflection(
|
||||
frame.subframes[ch].sf, estimate_order,
|
||||
frame.subframes[ch].samples, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2, sections,
|
||||
frame.subframes[ch].obits * 2 + BitReader.log2i(frame.blocksize) >= 61);
|
||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, estimate_order, 4.5, 0.0);
|
||||
frame.subframes[ch].best.size
|
||||
= (uint)Math.Max(0, frame.blocksize * (Math.Log(lpc_ctx.prediction_error[lpc_ctx.best_orders[0] - 1])) + Math.Log(frame.blocksize) * lpc_ctx.best_orders[0] * 4.5
|
||||
//= (uint)Math.Max(0, lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0)
|
||||
//* 2.0 / Math.Log(windowScale[0] / frame.blocksize)
|
||||
+ 7.1 * frame.subframes[ch].obits * m_settings.MaxLPCOrder);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case StereoMethod.Evaluate:
|
||||
for (int ch = 0; ch < subframes; ch++)
|
||||
encode_residual_pass1(frame, ch, 0);
|
||||
encode_residual_pass1(frame, ch, 1);
|
||||
break;
|
||||
case StereoMethod.Search:
|
||||
for (int ch = 0; ch < subframes; ch++)
|
||||
@@ -1538,11 +2001,18 @@ new int[] { // 30
|
||||
int sz = _windowsize;
|
||||
float* pos1 = window + _windowcount * Flake.MAX_BLOCKSIZE * 2;
|
||||
float* pos = pos1;
|
||||
int nSeg = 0;
|
||||
do
|
||||
{
|
||||
windowSections[nSeg, _windowcount, 0].setData(0, sz);
|
||||
for (int j = 1; j < lpc.MAX_LPC_SECTIONS; j++)
|
||||
windowSections[nSeg, _windowcount, j].setZero(sz, sz);
|
||||
|
||||
fixed (LpcWindowSection* sections = &windowSections[nSeg, _windowcount, 0])
|
||||
func(pos, sz);
|
||||
if ((sz & 1) != 0)
|
||||
break;
|
||||
nSeg++;
|
||||
pos += sz;
|
||||
sz >>= 1;
|
||||
} while (sz >= 32);
|
||||
@@ -1550,6 +2020,7 @@ new int[] { // 30
|
||||
for (int i = 0; i < _windowsize; i++)
|
||||
scale += pos1[i] * pos1[i];
|
||||
windowScale[_windowcount] = scale;
|
||||
windowType[_windowcount] = flag;
|
||||
_windowcount++;
|
||||
}
|
||||
|
||||
@@ -1569,13 +2040,77 @@ new int[] { // 30
|
||||
calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
|
||||
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
|
||||
calculate_window(window, lpc.window_bartlett, WindowFunction.Bartlett);
|
||||
int tukey_parts = 2;
|
||||
double overlap = -0.3;
|
||||
double overlap_units = overlap / (1.0 - overlap);
|
||||
for (int m = 0; m < tukey_parts; m++)
|
||||
calculate_window(window, (w, wsz) =>
|
||||
{
|
||||
lpc.window_punchout_tukey(w, wsz, 0.1,
|
||||
m / (tukey_parts + overlap_units),
|
||||
(m + 1 + overlap_units) / (tukey_parts + overlap_units));
|
||||
}, WindowFunction.PartialTukey);
|
||||
|
||||
tukey_parts = 3;
|
||||
overlap = -0.1;
|
||||
//overlap = 0.1;
|
||||
overlap_units = overlap / (1.0 - overlap);
|
||||
for (int m = 0; m < tukey_parts; m++)
|
||||
calculate_window(window, (w, wsz) =>
|
||||
{
|
||||
lpc.window_punchout_tukey(w, wsz, 0.1,
|
||||
m / (tukey_parts + overlap_units),
|
||||
(m + 1 + overlap_units) / (tukey_parts + overlap_units));
|
||||
}, WindowFunction.PunchoutTukey);
|
||||
if (_windowcount == 0)
|
||||
throw new Exception("invalid windowfunction");
|
||||
int nSeg = 0;
|
||||
int sz = _windowsize;
|
||||
float* window_segment = window;
|
||||
do
|
||||
{
|
||||
fixed (LpcWindowSection* sections = &windowSections[nSeg, 0, 0])
|
||||
LpcWindowSection.Detect(_windowcount, window_segment, Flake.MAX_BLOCKSIZE * 2, sz, sections);
|
||||
if ((sz & 1) != 0)
|
||||
break;
|
||||
window_segment += sz;
|
||||
nSeg++;
|
||||
sz >>= 1;
|
||||
} while (sz >= 32);
|
||||
#if NONONO
|
||||
using (TextWriter tx = File.CreateText("C:\\Temp\\w.csv"))
|
||||
{
|
||||
int totaltotal = 0;
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
int total = 0;
|
||||
for (int sec = 0; sec < lpc.MAX_LPC_SECTIONS; sec++)
|
||||
if (windowSections[0, i, sec].m_type != LpcWindowSection.SectionType.Zero || windowSections[0, i, sec].m_start != windowSections[0, i, sec].m_end)
|
||||
{
|
||||
tx.WriteLine("{0}\t{1}\t{2}", windowSections[0, i, sec].m_start, windowSections[0, i, sec].m_end, windowSections[0, i, sec].m_type);
|
||||
if (windowSections[0, i, sec].m_type != LpcWindowSection.SectionType.One)
|
||||
total += windowSections[0, i, sec].m_end - windowSections[0, i, sec].m_start;
|
||||
}
|
||||
totaltotal += total;
|
||||
tx.WriteLine("{0} total window data", total);
|
||||
}
|
||||
tx.WriteLine("{0} grand total window data", totaltotal);
|
||||
for (int x = 0; x < frame.blocksize; x++)
|
||||
{
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
tx.Write("{0}\t", window[i * Flake.MAX_BLOCKSIZE * 2 + x]);
|
||||
}
|
||||
tx.WriteLine();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (channels != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent)
|
||||
{
|
||||
frame.window_buffer = window;
|
||||
frame.nSeg = 0;
|
||||
frame.current.residual = r + channels * Flake.MAX_BLOCKSIZE;
|
||||
frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight;
|
||||
for (int ch = 0; ch < channels; ch++)
|
||||
@@ -1589,6 +2124,7 @@ new int[] { // 30
|
||||
{
|
||||
//channel_decorrelation(s, s + Flake.MAX_BLOCKSIZE, s + 2 * Flake.MAX_BLOCKSIZE, s + 3 * Flake.MAX_BLOCKSIZE, frame.blocksize);
|
||||
frame.window_buffer = window;
|
||||
frame.nSeg = 0;
|
||||
frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE;
|
||||
for (int ch = 0; ch < 4; ch++)
|
||||
frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE,
|
||||
@@ -1610,6 +2146,7 @@ new int[] { // 30
|
||||
{
|
||||
frame2.InitSize(frame.blocksize / 2, true);
|
||||
frame2.window_buffer = frame.window_buffer + frame.blocksize;
|
||||
frame2.nSeg++;
|
||||
frame2.current.residual = r + tumbler * 5 * Flake.MAX_BLOCKSIZE;
|
||||
for (int ch = 0; ch < 4; ch++)
|
||||
frame2.subframes[ch].Init(frame.subframes[ch].samples, frame2.current.residual + (ch + 1) * frame2.blocksize,
|
||||
@@ -1621,6 +2158,7 @@ new int[] { // 30
|
||||
{
|
||||
frame3.InitSize(frame2.blocksize, true);
|
||||
frame3.window_buffer = frame2.window_buffer;
|
||||
frame3.nSeg = frame2.nSeg;
|
||||
frame3.current.residual = frame2.current.residual + 5 * frame2.blocksize;
|
||||
for (int ch = 0; ch < 4; ch++)
|
||||
frame3.subframes[ch].Init(frame2.subframes[ch].samples + frame2.blocksize, frame3.current.residual + (ch + 1) * frame3.blocksize,
|
||||
@@ -2071,12 +2609,12 @@ new int[] { // 30
|
||||
public int flake_set_defaults(FlakeWriterSettings settings)
|
||||
{
|
||||
// default to level 7 params
|
||||
window_function = WindowFunction.Flattop | WindowFunction.Tukey;
|
||||
window_function = WindowFunction.PunchoutTukey | WindowFunction.PartialTukey | WindowFunction.Tukey;
|
||||
order_method = OrderMethod.Akaike;
|
||||
stereo_method = StereoMethod.Evaluate;
|
||||
window_method = WindowMethod.Evaluate;
|
||||
window_method = WindowMethod.EvaluateN;
|
||||
block_time_ms = 105;
|
||||
prediction_type = PredictionType.Search;
|
||||
prediction_type = PredictionType.Levinson;
|
||||
estimation_depth = 1;
|
||||
variable_block_size = 0;
|
||||
lpc_min_precision_search = 1;
|
||||
@@ -2088,37 +2626,45 @@ new int[] { // 30
|
||||
switch (settings.EncoderModeIndex)
|
||||
{
|
||||
case 0:
|
||||
block_time_ms = 53;
|
||||
prediction_type = PredictionType.Fixed;
|
||||
stereo_method = StereoMethod.Independent;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.Tukey;
|
||||
break;
|
||||
case 1:
|
||||
prediction_type = PredictionType.Levinson;
|
||||
prediction_type = PredictionType.Fixed;
|
||||
stereo_method = StereoMethod.Independent;
|
||||
window_function = WindowFunction.Bartlett;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.Tukey;
|
||||
break;
|
||||
case 2:
|
||||
stereo_method = StereoMethod.Independent;
|
||||
window_function = WindowFunction.Bartlett;
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.PartialTukey;
|
||||
break;
|
||||
case 3:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_function = WindowFunction.Bartlett;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.PunchoutTukey;
|
||||
break;
|
||||
case 4:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_function = WindowFunction.Bartlett;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.PunchoutTukey;
|
||||
estimation_depth = 2;
|
||||
break;
|
||||
case 5:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_method = WindowMethod.Estimate;
|
||||
window_function = WindowFunction.PunchoutTukey;
|
||||
break;
|
||||
case 6:
|
||||
stereo_method = StereoMethod.Estimate;
|
||||
window_method = WindowMethod.EstimateN;
|
||||
window_function = WindowFunction.PunchoutTukey | WindowFunction.PartialTukey;
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
prediction_type = PredictionType.Search;
|
||||
estimation_depth = 2;
|
||||
lpc_min_precision_search = 0;
|
||||
break;
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace CUETools.Codecs.FLAKE
|
||||
Independent = 0,
|
||||
Estimate = 1,
|
||||
Evaluate = 2,
|
||||
Search = 3
|
||||
Search = 3,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
{
|
||||
public enum WindowFunction
|
||||
{
|
||||
None = 0,
|
||||
Welch = 1,
|
||||
Tukey = 2,
|
||||
Hann = 4,
|
||||
Flattop = 8,
|
||||
Bartlett = 16,
|
||||
TukeyFlattop = 10
|
||||
TukeyFlattop = 10,
|
||||
PartialTukey = 32,
|
||||
TukeyPartialTukey = 34,
|
||||
TukeyFlattopPartialTukey = 42,
|
||||
PunchoutTukey = 64,
|
||||
TukeyFlattopPartialTukeyPunchoutTukey = 106,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
{
|
||||
public enum WindowMethod
|
||||
{
|
||||
Estimate = 0,
|
||||
Evaluate = 1,
|
||||
Search = 2
|
||||
Evaluate,
|
||||
Search,
|
||||
Estimate,
|
||||
Estimate2,
|
||||
Estimate3,
|
||||
EstimateN,
|
||||
Evaluate2,
|
||||
Evaluate2N,
|
||||
Evaluate3,
|
||||
Evaluate3N,
|
||||
EvaluateN,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,19 @@ namespace CUETools.Codecs
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasDefaultValuesForMode(int index)
|
||||
{
|
||||
bool res = true;
|
||||
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
|
||||
foreach (var attribute in property.Attributes)
|
||||
if (attribute is DefaultValueForModeAttribute)
|
||||
{
|
||||
var defaultValueForMode = attribute as DefaultValueForModeAttribute;
|
||||
res &= (int)property.GetValue(this) == defaultValueForMode.m_values[index];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
[XmlIgnore]
|
||||
public AudioPCMConfig PCM
|
||||
|
||||
@@ -5,8 +5,9 @@ namespace CUETools.Codecs
|
||||
public class lpc
|
||||
{
|
||||
public const int MAX_LPC_ORDER = 32;
|
||||
public const int MAX_LPC_WINDOWS = 2;
|
||||
public const int MAX_LPC_WINDOWS = 8;
|
||||
public const int MAX_LPC_PRECISIONS = 4;
|
||||
public const int MAX_LPC_SECTIONS = 32;
|
||||
|
||||
public unsafe static void window_welch(float* window, int L)
|
||||
{
|
||||
@@ -48,17 +49,47 @@ namespace CUETools.Codecs
|
||||
|
||||
public unsafe static void window_tukey(float* window, int L)
|
||||
{
|
||||
window_rectangle(window, L);
|
||||
double p = 0.5;
|
||||
int Np = (int)(p / 2.0 * L) - 1;
|
||||
int z = 0;
|
||||
int Np = (int)(p / 2.0 * L) - z;
|
||||
if (Np > 0)
|
||||
{
|
||||
for (int n = 0; n <= Np; n++)
|
||||
{
|
||||
window[n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * n / Np));
|
||||
window[L - Np - 1 + n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * (n + Np) / Np));
|
||||
for (int n = 0; n < z; n++)
|
||||
window[n] = window[L - n - 1] = 0;
|
||||
for (int n = 0; n < Np - 1; n++)
|
||||
window[n + z] = window[L - n - 1 - z] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * (n + 1) / Np));
|
||||
for (int n = z + Np - 1; n < L - z - Np + 1; n++)
|
||||
window[n] = 1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe static void window_punchout_tukey(float* window, int L, double p, double start, double end)
|
||||
{
|
||||
int start_n = (int)(start * L);
|
||||
int end_n = (int)(end * L);
|
||||
int Np = (int)(p / 2.0 * L);
|
||||
int i, n = 0;
|
||||
|
||||
if (start_n != 0)
|
||||
{
|
||||
for (i = 1; n < Np; n++, i++)
|
||||
window[n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * i / Np));
|
||||
for (; n < start_n - Np; n++)
|
||||
window[n] = 1.0f;
|
||||
for (i = Np; n < start_n; n++, i--)
|
||||
window[n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * i / Np));
|
||||
}
|
||||
for (; n < end_n; n++)
|
||||
window[n] = 0.0f;
|
||||
if (end_n != L)
|
||||
{
|
||||
for (i = 1; n < end_n + Np; n++, i++)
|
||||
window[n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * i / Np));
|
||||
for (; n < L - Np; n++)
|
||||
window[n] = 1.0f;
|
||||
for (i = Np; n < L; n++, i--)
|
||||
window[n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * i / Np));
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe static void window_hann(float* window, int L)
|
||||
@@ -73,6 +104,7 @@ namespace CUETools.Codecs
|
||||
return (short)((val >> 31) + ((val - 1) >> 31) + 1);
|
||||
}
|
||||
|
||||
#if XXX
|
||||
static public unsafe void
|
||||
compute_corr_int(/*const*/ short* data1, short* data2, int len, int min, int lag, int* autoc)
|
||||
{
|
||||
@@ -92,13 +124,14 @@ namespace CUETools.Codecs
|
||||
autoc[i] = temp + temp2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Calculates autocorrelation data from audio samples
|
||||
* A window function is applied before calculation.
|
||||
*/
|
||||
static public unsafe void
|
||||
compute_autocorr(/*const*/ int* data, int len, int min, int lag, double* autoc, float* window)
|
||||
compute_autocorr(/*const*/ int* data, float* window, int len, int min, int lag, double* autoc, int prev, int next)
|
||||
{
|
||||
#if FPAC
|
||||
short* data1 = stackalloc short[len + 1];
|
||||
@@ -125,29 +158,223 @@ namespace CUETools.Codecs
|
||||
for (int coeff = min; coeff <= lag; coeff++)
|
||||
autoc[coeff] = (c1[coeff] * (double)(1 << 18) + (c2[coeff] + c3[coeff]) * (double)(1 << 9) + c4[coeff]);
|
||||
#else
|
||||
double* data1 = stackalloc double[(int)len + 16];
|
||||
#if XXX
|
||||
if (min == 0 && lag >= 4)
|
||||
{
|
||||
int* pdata = data;
|
||||
float* pwindow = window;
|
||||
|
||||
double temp0 = 1.0;
|
||||
double temp1 = 1.0;
|
||||
double temp2 = 1.0;
|
||||
double temp3 = 1.0;
|
||||
double temp4 = 1.0;
|
||||
|
||||
double c0 = *(pdata++) * *(pwindow++);
|
||||
float c1 = *(pdata++) * *(pwindow++);
|
||||
float c2 = *(pdata++) * *(pwindow++);
|
||||
float c3 = *(pdata++) * *(pwindow++);
|
||||
float c4 = *(pdata++) * *(pwindow++);
|
||||
|
||||
int* finish = data + len;
|
||||
|
||||
while (pdata <= finish)
|
||||
{
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * c1;
|
||||
temp2 += c0 * c2;
|
||||
temp3 += c0 * c3;
|
||||
temp4 += c0 * c4;
|
||||
|
||||
c0 = c1;
|
||||
c1 = c2;
|
||||
c2 = c3;
|
||||
c3 = c4;
|
||||
c4 = *(pdata++) * *(pwindow++);
|
||||
}
|
||||
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * c1;
|
||||
temp2 += c0 * c2;
|
||||
temp3 += c0 * c3;
|
||||
c0 = c1;
|
||||
c1 = c2;
|
||||
c2 = c3;
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * c1;
|
||||
temp2 += c0 * c2;
|
||||
c0 = c1;
|
||||
c1 = c2;
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * c1;
|
||||
c0 = c1;
|
||||
temp0 += c0 * c0;
|
||||
|
||||
autoc[0] += temp0;
|
||||
autoc[1] += temp1;
|
||||
autoc[2] += temp2;
|
||||
autoc[3] += temp3;
|
||||
autoc[4] += temp4;
|
||||
min = 5;
|
||||
|
||||
if (lag < min) return;
|
||||
}
|
||||
#endif
|
||||
double* data1 = stackalloc double[lag + len + lag];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lag; i++)
|
||||
data1[i] = prev != 0 ? data[i - lag] : 0;
|
||||
for (i = 0; i < len; i++)
|
||||
data1[i] = data[i] * window[i];
|
||||
data1[len] = 0;
|
||||
data1[lag + i] = data[i] * window[i];
|
||||
for (i = 0; i < lag; i++)
|
||||
data1[lag + len + i] = next != 0 ? data[len + i] : 0;
|
||||
|
||||
for (i = min; i <= lag; ++i)
|
||||
{
|
||||
double temp = 1.0;
|
||||
double temp2 = 1.0;
|
||||
double* finish = data1 + len - i;
|
||||
double temp = 0;
|
||||
double temp2 = 0;
|
||||
double* pdata = data1 + lag - i;
|
||||
double* finish = data1 + lag + len - 1;
|
||||
|
||||
for (double* pdata = data1; pdata < finish; pdata += 2)
|
||||
while (pdata < finish)
|
||||
{
|
||||
temp += pdata[i] * pdata[0];
|
||||
temp2 += pdata[i + 1] * pdata[1];
|
||||
temp += pdata[i] * (*pdata++);
|
||||
temp2 += pdata[i] * (*pdata++);
|
||||
}
|
||||
autoc[i] = temp + temp2;
|
||||
if (pdata <= finish)
|
||||
temp += pdata[i] * (*pdata++);
|
||||
|
||||
autoc[i] += temp + temp2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static public unsafe void
|
||||
compute_autocorr_windowless(/*const*/ int* data, int len, int min, int lag, double* autoc)
|
||||
{
|
||||
// if databits*2 + log2(len) <= 64
|
||||
#if !XXX
|
||||
#if XXX
|
||||
if (min == 0 && lag >= 4)
|
||||
{
|
||||
long temp0 = 0;
|
||||
long temp1 = 0;
|
||||
long temp2 = 0;
|
||||
long temp3 = 0;
|
||||
long temp4 = 0;
|
||||
int* pdata = data;
|
||||
int* finish = data + len - 4;
|
||||
while (pdata < finish)
|
||||
{
|
||||
long c0 = *(pdata++);
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * pdata[0];
|
||||
temp2 += c0 * pdata[1];
|
||||
temp3 += c0 * pdata[2];
|
||||
temp4 += c0 * pdata[3];
|
||||
}
|
||||
{
|
||||
long c0 = *(pdata++);
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * pdata[0];
|
||||
temp2 += c0 * pdata[1];
|
||||
temp3 += c0 * pdata[2];
|
||||
}
|
||||
{
|
||||
long c0 = *(pdata++);
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * pdata[0];
|
||||
temp2 += c0 * pdata[1];
|
||||
}
|
||||
{
|
||||
long c0 = *(pdata++);
|
||||
temp0 += c0 * c0;
|
||||
temp1 += c0 * pdata[0];
|
||||
}
|
||||
{
|
||||
long c0 = *(pdata++);
|
||||
temp0 += c0 * c0;
|
||||
}
|
||||
autoc[0] += temp0;
|
||||
autoc[1] += temp1;
|
||||
autoc[2] += temp2;
|
||||
autoc[3] += temp3;
|
||||
autoc[4] += temp4;
|
||||
min = 5;
|
||||
|
||||
if (lag < min) return;
|
||||
}
|
||||
#endif
|
||||
for (int i = min; i <= lag; ++i)
|
||||
{
|
||||
long temp = 0;
|
||||
long temp2 = 0;
|
||||
int* pdata = data;
|
||||
int* finish = data + len - i - 1;
|
||||
while (pdata < finish)
|
||||
{
|
||||
temp += (long)pdata[i] * (*pdata++);
|
||||
temp2 += (long)pdata[i] * (*pdata++);
|
||||
}
|
||||
if (pdata <= finish)
|
||||
temp += (long)pdata[i] * (*pdata++);
|
||||
autoc[i] += temp + temp2;
|
||||
}
|
||||
#else
|
||||
for (int i = min; i <= lag; ++i)
|
||||
{
|
||||
double temp = 0;
|
||||
double temp2 = 0;
|
||||
int* pdata = data;
|
||||
int* finish = data + len - i - 1;
|
||||
|
||||
while (pdata < finish)
|
||||
{
|
||||
temp += (double)pdata[i] * (double)(*pdata++);
|
||||
temp2 += (double)pdata[i] * (double)(*pdata++);
|
||||
}
|
||||
if (pdata <= finish)
|
||||
temp += (double)pdata[i] * (double)(*pdata++);
|
||||
autoc[i] += temp + temp2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static public unsafe void
|
||||
compute_autocorr_windowless_large(/*const*/ int* data, int len, int min, int lag, double* autoc)
|
||||
{
|
||||
for (int i = min; i <= lag; ++i)
|
||||
{
|
||||
double temp = 0;
|
||||
double temp2 = 0;
|
||||
int* pdata = data;
|
||||
int* finish = data + len - i - 1;
|
||||
while (pdata < finish)
|
||||
{
|
||||
temp += (long)pdata[i] * (*pdata++);
|
||||
temp2 += (long)pdata[i] * (*pdata++);
|
||||
}
|
||||
if (pdata <= finish)
|
||||
temp += (long)pdata[i] * (*pdata++);
|
||||
autoc[i] += temp + temp2;
|
||||
}
|
||||
}
|
||||
|
||||
static public unsafe void
|
||||
compute_autocorr_glue(/*const*/ int* data, int min, int lag, double* autoc)
|
||||
{
|
||||
for (int i = min; i <= lag; ++i)
|
||||
{
|
||||
long temp = 0;
|
||||
int* pdata = data - i;
|
||||
int* finish = data;
|
||||
while (pdata < finish)
|
||||
temp += (long)pdata[i] * (*pdata++);
|
||||
autoc[i] += temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Levinson-Durbin recursion.
|
||||
* Produces LPC coefficients from autocorrelation data.
|
||||
|
||||
@@ -1,7 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
unsafe public class LpcSubframeInfo
|
||||
{
|
||||
public LpcSubframeInfo()
|
||||
{
|
||||
autocorr_section_values = new double[lpc.MAX_LPC_SECTIONS, lpc.MAX_LPC_ORDER + 1];
|
||||
autocorr_section_orders = new int[lpc.MAX_LPC_SECTIONS];
|
||||
}
|
||||
|
||||
// public LpcContext[] lpc_ctx;
|
||||
public double[,] autocorr_section_values;
|
||||
public int[] autocorr_section_orders;
|
||||
//public int obits;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
for (int sec = 0; sec < autocorr_section_orders.Length; sec++)
|
||||
autocorr_section_orders[sec] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe public struct LpcWindowSection
|
||||
{
|
||||
public enum SectionType
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Data,
|
||||
Glue
|
||||
};
|
||||
public int m_start;
|
||||
public int m_end;
|
||||
public SectionType m_type;
|
||||
public int m_id;
|
||||
public LpcWindowSection(int end)
|
||||
{
|
||||
m_id = -1;
|
||||
m_start = 0;
|
||||
m_end = end;
|
||||
m_type = SectionType.Data;
|
||||
}
|
||||
public void setData(int start, int end)
|
||||
{
|
||||
m_id = -1;
|
||||
m_start = start;
|
||||
m_end = end;
|
||||
m_type = SectionType.Data;
|
||||
}
|
||||
public void setOne(int start, int end)
|
||||
{
|
||||
m_id = -1;
|
||||
m_start = start;
|
||||
m_end = end;
|
||||
m_type = SectionType.One;
|
||||
}
|
||||
public void setGlue(int start)
|
||||
{
|
||||
m_id = -1;
|
||||
m_start = start;
|
||||
m_end = start;
|
||||
m_type = SectionType.Glue;
|
||||
}
|
||||
public void setZero(int start, int end)
|
||||
{
|
||||
m_id = -1;
|
||||
m_start = start;
|
||||
m_end = end;
|
||||
m_type = SectionType.Zero;
|
||||
}
|
||||
|
||||
unsafe public static void Detect(int _windowcount, float* window_segment, int stride, int sz, LpcWindowSection* sections)
|
||||
{
|
||||
int section_id = 0;
|
||||
var boundaries = new List<int>();
|
||||
var types = new LpcWindowSection.SectionType[_windowcount, lpc.MAX_LPC_SECTIONS * 2];
|
||||
for (int x = 0; x < sz; x++)
|
||||
{
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
float w = window_segment[i * stride + x];
|
||||
types[i, boundaries.Count] =
|
||||
boundaries.Count >= lpc.MAX_LPC_SECTIONS * 2 - 2 ?
|
||||
LpcWindowSection.SectionType.Data : w == 0.0 ?
|
||||
LpcWindowSection.SectionType.Zero : w == 1.0 ?
|
||||
LpcWindowSection.SectionType.One :
|
||||
LpcWindowSection.SectionType.Data;
|
||||
}
|
||||
bool isBoundary = false;
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
isBoundary |= boundaries.Count == 0 ||
|
||||
types[i, boundaries.Count - 1] != types[i, boundaries.Count];
|
||||
}
|
||||
if (isBoundary) boundaries.Add(x);
|
||||
}
|
||||
boundaries.Add(sz);
|
||||
var ones = new int[boundaries.Count - 1];
|
||||
// Reconstruct segments list.
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
int secs = 0;
|
||||
for (int j = 0; j < boundaries.Count - 1; j++)
|
||||
{
|
||||
if (types[i, j] == LpcWindowSection.SectionType.Zero)
|
||||
{
|
||||
if (secs > 0 && sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_end == boundaries[j] && sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_type == LpcWindowSection.SectionType.Zero)
|
||||
{
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_end = boundaries[j + 1];
|
||||
continue;
|
||||
}
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs++].setZero(boundaries[j], boundaries[j + 1]);
|
||||
continue;
|
||||
}
|
||||
if (types[i, j] == LpcWindowSection.SectionType.Data
|
||||
|| secs + 1 >= lpc.MAX_LPC_SECTIONS
|
||||
|| (boundaries[j + 1] - boundaries[j] < lpc.MAX_LPC_ORDER))
|
||||
{
|
||||
if (secs > 0 && sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_end == boundaries[j] && sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_type == LpcWindowSection.SectionType.Data)
|
||||
{
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_end = boundaries[j + 1];
|
||||
continue;
|
||||
}
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs++].setData(boundaries[j], boundaries[j + 1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (secs > 0 && sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_end == boundaries[j] && sections[i * lpc.MAX_LPC_SECTIONS + secs - 1].m_type == LpcWindowSection.SectionType.One)
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs++].setGlue(boundaries[j]);
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs++].setOne(boundaries[j], boundaries[j + 1]);
|
||||
ones[j] |= 1 << i;
|
||||
}
|
||||
while (secs < lpc.MAX_LPC_SECTIONS)
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + secs++].setZero(sz, sz);
|
||||
}
|
||||
for (int j = 0; j < boundaries.Count - 1; j++)
|
||||
{
|
||||
if (j > 0 && ones[j - 1] == ones[j])
|
||||
{
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
{
|
||||
for (int sec = 0; sec < lpc.MAX_LPC_SECTIONS; sec++)
|
||||
if (sections[i * lpc.MAX_LPC_SECTIONS + sec].m_type == LpcWindowSection.SectionType.Glue &&
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + sec].m_start == boundaries[j])
|
||||
{
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + sec - 1].m_end = sections[i * lpc.MAX_LPC_SECTIONS + sec + 1].m_end;
|
||||
for (int sec1 = sec; sec1 + 2 < lpc.MAX_LPC_SECTIONS; sec1++)
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + sec1] = sections[i * lpc.MAX_LPC_SECTIONS + sec1 + 2];
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((ones[j] & (ones[j] - 1)) != 0 && section_id < lpc.MAX_LPC_SECTIONS)
|
||||
{
|
||||
for (int i = 0; i < _windowcount; i++)
|
||||
for (int sec = 0; sec < lpc.MAX_LPC_SECTIONS; sec++)
|
||||
if (sections[i * lpc.MAX_LPC_SECTIONS + sec].m_type == LpcWindowSection.SectionType.One &&
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + sec].m_start == boundaries[j])
|
||||
{
|
||||
sections[i * lpc.MAX_LPC_SECTIONS + sec].m_id = section_id;
|
||||
}
|
||||
section_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context for LPC coefficients calculation and order estimation
|
||||
/// </summary>
|
||||
@@ -36,18 +202,62 @@ namespace CUETools.Codecs
|
||||
/// <param name="samples">Samples pointer</param>
|
||||
/// <param name="blocksize">Block size</param>
|
||||
/// <param name="window">Window function</param>
|
||||
public void GetReflection(int order, int* samples, int blocksize, float* window)
|
||||
public void GetReflection(LpcSubframeInfo subframe, int order, int* samples, float* window, LpcWindowSection* sections, bool large)
|
||||
{
|
||||
if (autocorr_order > order)
|
||||
return;
|
||||
fixed (double* reff = reflection_coeffs, autoc = autocorr_values, err = prediction_error)
|
||||
{
|
||||
lpc.compute_autocorr(samples, blocksize, autocorr_order, order, autoc, window);
|
||||
for (int i = autocorr_order; i <= order; i++) autoc[i] = 0;
|
||||
int prev = 0;
|
||||
for (int section = 0; section < lpc.MAX_LPC_SECTIONS; section++)
|
||||
{
|
||||
if (sections[section].m_type == LpcWindowSection.SectionType.Zero)
|
||||
{
|
||||
prev = 0;
|
||||
continue;
|
||||
}
|
||||
if (sections[section].m_type == LpcWindowSection.SectionType.Data)
|
||||
{
|
||||
int next = section + 1 < lpc.MAX_LPC_SECTIONS && sections[section + 1].m_type == LpcWindowSection.SectionType.One ? 1 : 0;
|
||||
lpc.compute_autocorr(samples + sections[section].m_start, window + sections[section].m_start, sections[section].m_end - sections[section].m_start, autocorr_order, order, autoc, prev, next);
|
||||
}
|
||||
else if (sections[section].m_type == LpcWindowSection.SectionType.Glue)
|
||||
lpc.compute_autocorr_glue(samples + sections[section].m_start, autocorr_order, order, autoc);
|
||||
else if (sections[section].m_type == LpcWindowSection.SectionType.One)
|
||||
{
|
||||
if (sections[section].m_id >= 0)
|
||||
{
|
||||
if (subframe.autocorr_section_orders[sections[section].m_id] <= order)
|
||||
{
|
||||
fixed (double* autocsec = &subframe.autocorr_section_values[sections[section].m_id, 0])
|
||||
{
|
||||
for (int i = subframe.autocorr_section_orders[sections[section].m_id]; i <= order; i++) autocsec[i] = 0;
|
||||
if (large)
|
||||
lpc.compute_autocorr_windowless_large(samples + sections[section].m_start, sections[section].m_end - sections[section].m_start, subframe.autocorr_section_orders[sections[section].m_id], order, autocsec);
|
||||
else
|
||||
lpc.compute_autocorr_windowless(samples + sections[section].m_start, sections[section].m_end - sections[section].m_start, subframe.autocorr_section_orders[sections[section].m_id], order, autocsec);
|
||||
}
|
||||
subframe.autocorr_section_orders[sections[section].m_id] = order + 1;
|
||||
}
|
||||
for (int i = autocorr_order; i <= order; i++)
|
||||
autoc[i] += subframe.autocorr_section_values[sections[section].m_id, i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (large)
|
||||
lpc.compute_autocorr_windowless_large(samples + sections[section].m_start, sections[section].m_end - sections[section].m_start, autocorr_order, order, autoc);
|
||||
else
|
||||
lpc.compute_autocorr_windowless(samples + sections[section].m_start, sections[section].m_end - sections[section].m_start, autocorr_order, order, autoc);
|
||||
}
|
||||
prev = 1;
|
||||
}
|
||||
}
|
||||
lpc.compute_schur_reflection(autoc, (uint)order, reff, err);
|
||||
autocorr_order = order + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if XXX
|
||||
public void GetReflection1(int order, int* samples, int blocksize, float* window)
|
||||
{
|
||||
if (autocorr_order > order)
|
||||
@@ -83,11 +293,12 @@ namespace CUETools.Codecs
|
||||
autocorr_order = order + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
public double Akaike(int blocksize, int order, double alpha, double beta)
|
||||
{
|
||||
//return (blocksize - order) * (Math.Log(prediction_error[order - 1]) - Math.Log(1.0)) + Math.Log(blocksize) * order * (alpha + beta * order);
|
||||
return blocksize * Math.Log(prediction_error[order - 1]) + Math.Log(blocksize) * order * (alpha + beta * order);
|
||||
//return blocksize * (Math.Log(prediction_error[order - 1]) - Math.Log(autocorr_values[0]) / 2) + Math.Log(blocksize) * order * (alpha + beta * order);
|
||||
return blocksize * (Math.Log(prediction_error[order - 1])) + Math.Log(blocksize) * order * (alpha + beta * order);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -475,25 +475,45 @@ namespace CUETools.FlakeExe
|
||||
|
||||
if (debug)
|
||||
{
|
||||
settings = flake.Settings as FlakeWriterSettings;
|
||||
Console.SetOut(stdout);
|
||||
Console.Out.WriteLine("{0}\t{1:0.00}\t{2}\t{3}\t{4}\t{5}\t{6}..{7}\t{8}..{9}\t{10}..{11}\t{12}..{13}\t{14}\t{15}\t{16}",
|
||||
Console.Out.WriteLine("{17}\t{0}\t{1:0.00}\t{2}\t{3}\t{4}\t{5}\t{6}..{7}\t{8}..{9}\t{10}..{11}\t{12}..{13}\t{14}\t{15}\t{16}\t{18}",
|
||||
flake.TotalSize,
|
||||
flake.UserProcessorTime.TotalSeconds > 0 ? flake.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds,
|
||||
flake.PredictionType.ToString().PadRight(15),
|
||||
flake.StereoMethod.ToString().PadRight(15),
|
||||
(flake.OrderMethod.ToString() + "(" + flake.EstimationDepth.ToString() + ")").PadRight(15),
|
||||
flake.WindowFunction,
|
||||
(flake.Settings as FlakeWriterSettings).MinPartitionOrder,
|
||||
(flake.Settings as FlakeWriterSettings).MaxPartitionOrder,
|
||||
(flake.Settings as FlakeWriterSettings).MinLPCOrder,
|
||||
(flake.Settings as FlakeWriterSettings).MaxLPCOrder,
|
||||
(flake.Settings as FlakeWriterSettings).MinFixedOrder,
|
||||
(flake.Settings as FlakeWriterSettings).MaxFixedOrder,
|
||||
(flake.WindowMethod.ToString().PadRight(10) + "(" +
|
||||
((flake.WindowFunction & WindowFunction.Tukey) != 0 ? "T" : " ") +
|
||||
((flake.WindowFunction & WindowFunction.PartialTukey) != 0 ? "P" : " ") +
|
||||
(((flake.WindowFunction & WindowFunction.PunchoutTukey) != 0 ? "O" : "") +
|
||||
((flake.WindowFunction & WindowFunction.Welch) == 0 ? "" : "W") +
|
||||
((flake.WindowFunction & WindowFunction.Hann) == 0 ? "" : "H") +
|
||||
((flake.WindowFunction & WindowFunction.Flattop) == 0 ? "" : "F") +
|
||||
((flake.WindowFunction & WindowFunction.Bartlett) == 0 ? "" : "B")).PadRight(1))
|
||||
+")",
|
||||
settings.MinPartitionOrder,
|
||||
settings.MaxPartitionOrder,
|
||||
settings.MinLPCOrder,
|
||||
settings.MaxLPCOrder,
|
||||
settings.MinFixedOrder,
|
||||
settings.MaxFixedOrder,
|
||||
flake.MinPrecisionSearch,
|
||||
flake.MaxPrecisionSearch,
|
||||
flake.Settings.BlockSize,
|
||||
flake.VBRMode,
|
||||
coeffs ?? ""
|
||||
coeffs ?? "",
|
||||
audioSource.Position * audioSource.PCM.BlockAlign,
|
||||
(flake.PredictionType == PredictionType.Search && flake.StereoMethod == StereoMethod.Evaluate && flake.WindowMethod == WindowMethod.EvaluateN && flake.WindowFunction == (WindowFunction.PunchoutTukey | WindowFunction.PartialTukey | WindowFunction.Tukey) && flake.EstimationDepth == 2 && flake.MinPrecisionSearch == 0 && settings.HasDefaultValuesForMode(8)) ? "8" :
|
||||
(flake.PredictionType == PredictionType.Levinson && flake.StereoMethod == StereoMethod.Evaluate && flake.WindowMethod == WindowMethod.EvaluateN && flake.WindowFunction == (WindowFunction.PunchoutTukey | WindowFunction.PartialTukey | WindowFunction.Tukey) && flake.EstimationDepth == 1 && flake.MinPrecisionSearch == 1 && settings.HasDefaultValuesForMode(7)) ? "7" :
|
||||
(flake.PredictionType == PredictionType.Levinson && flake.StereoMethod == StereoMethod.Evaluate && flake.WindowMethod == WindowMethod.EstimateN && flake.WindowFunction == (WindowFunction.PunchoutTukey | WindowFunction.PartialTukey) && flake.EstimationDepth == 1 && flake.MinPrecisionSearch == 1 && settings.HasDefaultValuesForMode(6)) ? "6" :
|
||||
(flake.PredictionType == PredictionType.Levinson && flake.StereoMethod == StereoMethod.Evaluate && flake.WindowMethod == WindowMethod.Estimate && flake.WindowFunction == WindowFunction.PunchoutTukey && flake.EstimationDepth == 1 && flake.MinPrecisionSearch == 1 && settings.HasDefaultValuesForMode(5)) ? "5" :
|
||||
(flake.PredictionType == PredictionType.Levinson && flake.StereoMethod == StereoMethod.Estimate && flake.WindowMethod == WindowMethod.Estimate && flake.WindowFunction == WindowFunction.PunchoutTukey && flake.EstimationDepth == 2 && flake.MinPrecisionSearch == 1 && settings.HasDefaultValuesForMode(4)) ? "4" :
|
||||
(flake.PredictionType == PredictionType.Levinson && flake.StereoMethod == StereoMethod.Estimate && flake.WindowMethod == WindowMethod.Estimate && flake.WindowFunction == WindowFunction.PunchoutTukey && flake.EstimationDepth == 1 && flake.MinPrecisionSearch == 1 && settings.HasDefaultValuesForMode(3)) ? "3" :
|
||||
(flake.PredictionType == PredictionType.Levinson && flake.StereoMethod == StereoMethod.Estimate && flake.WindowMethod == WindowMethod.Estimate && flake.WindowFunction == WindowFunction.PartialTukey && flake.EstimationDepth == 1 && flake.MinPrecisionSearch == 1 && settings.HasDefaultValuesForMode(2)) ? "2" :
|
||||
(flake.PredictionType == PredictionType.Fixed && flake.StereoMethod == StereoMethod.Independent && flake.WindowMethod == WindowMethod.Estimate && flake.MinPrecisionSearch == 1 && flake.WindowFunction == WindowFunction.Tukey && settings.HasDefaultValuesForMode(1)) ? "1" :
|
||||
(flake.PredictionType == PredictionType.Fixed && flake.StereoMethod == StereoMethod.Independent && flake.WindowMethod == WindowMethod.Estimate && flake.MinPrecisionSearch == 1 && flake.WindowFunction == WindowFunction.Tukey && settings.HasDefaultValuesForMode(0)) ? "0" :
|
||||
"?"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user