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 int* samples;
|
||||||
public uint done_fixed;
|
public uint done_fixed;
|
||||||
public LpcContext[] lpc_ctx;
|
public LpcContext[] lpc_ctx;
|
||||||
|
public LpcSubframeInfo sf;
|
||||||
|
|
||||||
public ALACSubframeInfo()
|
public ALACSubframeInfo()
|
||||||
{
|
{
|
||||||
best = new ALACSubframe();
|
best = new ALACSubframe();
|
||||||
lpc_ctx = new LpcContext[Alac.MAX_LPC_WINDOWS];
|
sf = new LpcSubframeInfo();
|
||||||
for (int i = 0; i < Alac.MAX_LPC_WINDOWS; i++)
|
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
|
||||||
|
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
|
||||||
lpc_ctx[i] = new LpcContext();
|
lpc_ctx[i] = new LpcContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +23,8 @@
|
|||||||
best.residual = r;
|
best.residual = r;
|
||||||
best.size = AudioSamples.UINT32_MAX;
|
best.size = AudioSamples.UINT32_MAX;
|
||||||
best.order = 0;
|
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();
|
lpc_ctx[iWindow].Reset();
|
||||||
done_fixed = 0;
|
done_fixed = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace CUETools.Codecs.ALAC
|
|||||||
public class ALACWriterSettings: AudioEncoderSettings
|
public class ALACWriterSettings: AudioEncoderSettings
|
||||||
{
|
{
|
||||||
public ALACWriterSettings()
|
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[] verifyBuffer;
|
||||||
int[] residualBuffer;
|
int[] residualBuffer;
|
||||||
float[] windowBuffer;
|
float[] windowBuffer;
|
||||||
|
LpcWindowSection[,] windowSections;
|
||||||
int samplesInBuffer = 0;
|
int samplesInBuffer = 0;
|
||||||
|
|
||||||
int m_blockSize = 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)];
|
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)];
|
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);
|
eparams.set_defaults(m_settings.EncoderModeIndex);
|
||||||
|
|
||||||
@@ -875,7 +877,11 @@ namespace CUETools.Codecs.ALAC
|
|||||||
|
|
||||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
|
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.ComputeLPC(lpcs);
|
||||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, min_order, max_order, 5.0, 1.0/18);
|
lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, min_order, max_order, 5.0, 1.0/18);
|
||||||
for (i = 0; i < eparams.estimation_depth && i < max_order; i++)
|
for (i = 0; i < eparams.estimation_depth && i < max_order; i++)
|
||||||
@@ -945,20 +951,36 @@ namespace CUETools.Codecs.ALAC
|
|||||||
{
|
{
|
||||||
case WindowMethod.Estimate:
|
case WindowMethod.Estimate:
|
||||||
{
|
{
|
||||||
int best_window = -1;
|
int order = 4;
|
||||||
double best_error = 0;
|
float* err = stackalloc float[lpc.MAX_LPC_ORDER];
|
||||||
int order = 2;
|
|
||||||
for (int i = 0; i < _windowcount; i++)
|
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);
|
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[i];
|
||||||
double err = frame.subframes[ch].lpc_ctx[i].prediction_error[order - 1] / frame.subframes[ch].lpc_ctx[i].autocorr_values[0];
|
fixed (LpcWindowSection* sections = &windowSections[i, 0])
|
||||||
if (best_window == -1 || best_error > err)
|
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;
|
for (int j = i + 1; j < _windowcount; j++)
|
||||||
best_error = err;
|
{
|
||||||
|
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:
|
case WindowMethod.Evaluate:
|
||||||
encode_residual_pass1(frame, ch, -1);
|
encode_residual_pass1(frame, ch, -1);
|
||||||
@@ -978,10 +1000,16 @@ namespace CUETools.Codecs.ALAC
|
|||||||
case StereoMethod.Estimate:
|
case StereoMethod.Estimate:
|
||||||
for (int ch = 0; ch < subframes; ch++)
|
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);
|
int stereo_order = Math.Min(8, eparams.max_prediction_order);
|
||||||
double alpha = 1.5; // 4.5 + eparams.max_prediction_order / 10.0;
|
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);
|
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));
|
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)
|
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;
|
return;
|
||||||
int sz = _windowsize;
|
int sz = _windowsize;
|
||||||
float* pos = window + _windowcount * Alac.MAX_BLOCKSIZE * 2;
|
float* pos = window + _windowcount * Alac.MAX_BLOCKSIZE * 2;
|
||||||
do
|
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);
|
func(pos, sz);
|
||||||
|
break;
|
||||||
if ((sz & 1) != 0)
|
if ((sz & 1) != 0)
|
||||||
break;
|
break;
|
||||||
pos += sz;
|
pos += sz;
|
||||||
@@ -1091,8 +1123,32 @@ namespace CUETools.Codecs.ALAC
|
|||||||
calculate_window(window, lpc.window_tukey, WindowFunction.Tukey);
|
calculate_window(window, lpc.window_tukey, WindowFunction.Tukey);
|
||||||
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
|
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
|
||||||
calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
|
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)
|
if (_windowcount == 0)
|
||||||
throw new Exception("invalid windowfunction");
|
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;
|
frame.window_buffer = window;
|
||||||
|
|
||||||
@@ -1793,11 +1849,13 @@ namespace CUETools.Codecs.ALAC
|
|||||||
case 4:
|
case 4:
|
||||||
stereo_method = StereoMethod.Estimate;
|
stereo_method = StereoMethod.Estimate;
|
||||||
window_method = WindowMethod.Estimate;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.PartialTukey | WindowFunction.PunchoutTukey;
|
||||||
max_prediction_order = 8;
|
max_prediction_order = 8;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
stereo_method = StereoMethod.Estimate;
|
stereo_method = StereoMethod.Estimate;
|
||||||
window_method = WindowMethod.Estimate;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.PartialTukey | WindowFunction.PunchoutTukey;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
stereo_method = StereoMethod.Estimate;
|
stereo_method = StereoMethod.Estimate;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ namespace CUETools.Codecs.ALAC
|
|||||||
public const int MAX_RICE_PARAM = 14;
|
public const int MAX_RICE_PARAM = 14;
|
||||||
public const int MAX_PARTITION_ORDER = 8;
|
public const int MAX_PARTITION_ORDER = 8;
|
||||||
public const int MAX_PARTITIONS = 1 << MAX_PARTITION_ORDER;
|
public const int MAX_PARTITIONS = 1 << MAX_PARTITION_ORDER;
|
||||||
public const int MAX_LPC_WINDOWS = 4;
|
|
||||||
|
|
||||||
public const uint UINT32_MAX = 0xffffffff;
|
public const uint UINT32_MAX = 0xffffffff;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
Hann = 4,
|
Hann = 4,
|
||||||
Flattop = 8,
|
Flattop = 8,
|
||||||
Bartlett = 16,
|
Bartlett = 16,
|
||||||
TukFlat = 10
|
TukFlat = 10,
|
||||||
|
PartialTukey = 32,
|
||||||
|
PunchoutTukey = 64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,6 +270,8 @@ namespace CUETools.Codecs.FLACCL
|
|||||||
string _path;
|
string _path;
|
||||||
long _position;
|
long _position;
|
||||||
|
|
||||||
|
public const int MAX_LPC_WINDOWS = 2;
|
||||||
|
|
||||||
// number of audio channels
|
// number of audio channels
|
||||||
// valid values are 1 to 8
|
// valid values are 1 to 8
|
||||||
int channels, ch_code;
|
int channels, ch_code;
|
||||||
@@ -1090,7 +1092,7 @@ namespace CUETools.Codecs.FLACCL
|
|||||||
|
|
||||||
unsafe void calculate_window(FLACCLTask task, window_function func, WindowFunction flag)
|
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;
|
return;
|
||||||
|
|
||||||
func(((float*)task.clWindowFunctionsPtr) + task.nWindowFunctions * task.frameSize, task.frameSize);
|
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 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 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 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 lpcDataLen = autocorLen * 32;
|
||||||
int resOutLen = sizeof(int) * channelsCount * (lpc.MAX_LPC_WINDOWS * lpc.MAX_LPC_ORDER + 8) * MAX_FRAMES;
|
int resOutLen = sizeof(int) * channelsCount * (FLACCLWriter.MAX_LPC_WINDOWS * lpc.MAX_LPC_ORDER + 8) * MAX_FRAMES;
|
||||||
int wndLen = sizeof(float) * MAX_CHANNELSIZE /** 2*/ * lpc.MAX_LPC_WINDOWS;
|
int wndLen = sizeof(float) * MAX_CHANNELSIZE /** 2*/ * FLACCLWriter.MAX_LPC_WINDOWS;
|
||||||
int selectedLen = sizeof(int) * 32 * channelsCount * MAX_FRAMES;
|
int selectedLen = sizeof(int) * 32 * channelsCount * MAX_FRAMES;
|
||||||
int riceLen = sizeof(int) * channels * MAX_CHANNELSIZE;
|
int riceLen = sizeof(int) * channels * MAX_CHANNELSIZE;
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
public int frame_number;
|
public int frame_number;
|
||||||
public FlacSubframe current;
|
public FlacSubframe current;
|
||||||
public float* window_buffer;
|
public float* window_buffer;
|
||||||
|
public int nSeg = 0;
|
||||||
|
|
||||||
public BitWriter writer = null;
|
public BitWriter writer = null;
|
||||||
public int writer_offset = 0;
|
public int writer_offset = 0;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public FlacSubframeInfo()
|
public FlacSubframeInfo()
|
||||||
{
|
{
|
||||||
best = new FlacSubframe();
|
best = new FlacSubframe();
|
||||||
|
sf = new LpcSubframeInfo();
|
||||||
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
|
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
|
||||||
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
|
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
|
||||||
lpc_ctx[i] = new LpcContext();
|
lpc_ctx[i] = new LpcContext();
|
||||||
@@ -22,8 +23,10 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
best.residual = r;
|
best.residual = r;
|
||||||
best.type = SubframeType.Verbatim;
|
best.type = SubframeType.Verbatim;
|
||||||
best.size = AudioSamples.UINT32_MAX;
|
best.size = AudioSamples.UINT32_MAX;
|
||||||
|
sf.Reset();
|
||||||
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++)
|
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++)
|
||||||
lpc_ctx[iWindow].Reset();
|
lpc_ctx[iWindow].Reset();
|
||||||
|
//sf.obits = obits;
|
||||||
done_fixed = 0;
|
done_fixed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,5 +36,6 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public int* samples;
|
public int* samples;
|
||||||
public uint done_fixed;
|
public uint done_fixed;
|
||||||
public LpcContext[] lpc_ctx;
|
public LpcContext[] lpc_ctx;
|
||||||
|
public LpcSubframeInfo sf;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define NOINTEROP
|
#define NOINTEROP
|
||||||
|
#define VARIANT1
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@@ -84,14 +85,14 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DefaultValue(-1)]
|
[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)]
|
[Browsable(false)]
|
||||||
[DisplayName("MinFixedOrder")]
|
[DisplayName("MinFixedOrder")]
|
||||||
[SRDescription(typeof(Properties.Resources), "MinFixedOrderDescription")]
|
[SRDescription(typeof(Properties.Resources), "MinFixedOrderDescription")]
|
||||||
public int MinFixedOrder { get; set; }
|
public int MinFixedOrder { get; set; }
|
||||||
|
|
||||||
[DefaultValue(-1)]
|
[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)]
|
[Browsable(false)]
|
||||||
[DisplayName("MaxFixedOrder")]
|
[DisplayName("MaxFixedOrder")]
|
||||||
[SRDescription(typeof(Properties.Resources), "MaxFixedOrderDescription")]
|
[SRDescription(typeof(Properties.Resources), "MaxFixedOrderDescription")]
|
||||||
@@ -104,7 +105,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public int MinLPCOrder { get; set; }
|
public int MinLPCOrder { get; set; }
|
||||||
|
|
||||||
[DefaultValue(-1)]
|
[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)]
|
[Browsable(false)]
|
||||||
[DisplayName("MaxLPCOrder")]
|
[DisplayName("MaxLPCOrder")]
|
||||||
[SRDescription(typeof(Properties.Resources), "MaxLPCOrderDescription")]
|
[SRDescription(typeof(Properties.Resources), "MaxLPCOrderDescription")]
|
||||||
@@ -117,7 +118,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public int MinPartitionOrder { get; set; }
|
public int MinPartitionOrder { get; set; }
|
||||||
|
|
||||||
[DefaultValue(-1)]
|
[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")]
|
[DisplayName("MaxPartitionOrder")]
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
[SRDescription(typeof(Properties.Resources), "MaxPartitionOrderDescription")]
|
[SRDescription(typeof(Properties.Resources), "MaxPartitionOrderDescription")]
|
||||||
@@ -192,6 +193,9 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
int[] residualBuffer;
|
int[] residualBuffer;
|
||||||
float[] windowBuffer;
|
float[] windowBuffer;
|
||||||
double[] windowScale;
|
double[] windowScale;
|
||||||
|
LpcWindowSection[, ,] windowSections;
|
||||||
|
|
||||||
|
WindowFunction[] windowType;
|
||||||
int samplesInBuffer = 0;
|
int samplesInBuffer = 0;
|
||||||
|
|
||||||
int m_blockSize = 0;
|
int m_blockSize = 0;
|
||||||
@@ -230,6 +234,8 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)];
|
residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)];
|
||||||
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];
|
||||||
|
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);
|
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)
|
unsafe static void encode_residual_fixed(int* res, int* smp, int n, int order)
|
||||||
{
|
{
|
||||||
int i;
|
int next_error_0, next_error_1, next_error_2, next_error_3, next_error_4;
|
||||||
int s0, s1, s2;
|
int last_error_0, last_error_1, last_error_2, last_error_3;
|
||||||
switch (order)
|
int* end = smp + n;
|
||||||
|
|
||||||
|
if (order == 0)
|
||||||
{
|
{
|
||||||
case 0:
|
|
||||||
AudioSamples.MemCpy(res, smp, n);
|
AudioSamples.MemCpy(res, smp, n);
|
||||||
return;
|
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)
|
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);
|
uint part = (1U << porder);
|
||||||
@@ -1079,6 +1319,21 @@ new int[] { // 30
|
|||||||
frame.current.order = order;
|
frame.current.order = order;
|
||||||
frame.current.type = SubframeType.Fixed;
|
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);
|
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);
|
int pmax = get_max_p_order(m_settings.MaxPartitionOrder, frame.blocksize, frame.current.order);
|
||||||
@@ -1091,7 +1346,78 @@ new int[] { // 30
|
|||||||
frame.ChooseBestSubframe(ch);
|
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* smp = frame.subframes[ch].samples;
|
||||||
int i, n = frame.blocksize;
|
int i, n = frame.blocksize;
|
||||||
@@ -1132,12 +1458,14 @@ new int[] { // 30
|
|||||||
|
|
||||||
for (int iWindow = 0; iWindow < _windowcount; iWindow++)
|
for (int iWindow = 0; iWindow < _windowcount; iWindow++)
|
||||||
{
|
{
|
||||||
if (best_window != -1 && iWindow != best_window)
|
if ((windows_mask & (1 << iWindow)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
|
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
|
||||||
|
fixed (LpcWindowSection* sections = &windowSections[frame.nSeg, iWindow, 0])
|
||||||
lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2);
|
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);
|
lpc_ctx.ComputeLPC(lpcs);
|
||||||
|
|
||||||
//int frameSize = n;
|
//int frameSize = n;
|
||||||
@@ -1217,9 +1545,22 @@ new int[] { // 30
|
|||||||
int max_fixed_order = Math.Min(m_settings.MaxFixedOrder, 4);
|
int max_fixed_order = Math.Min(m_settings.MaxFixedOrder, 4);
|
||||||
int min_fixed_order = Math.Min(m_settings.MinFixedOrder, 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++)
|
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);
|
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();
|
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_prediction_order = m_settings.MaxLPCOrder;
|
||||||
int max_fixed_order = m_settings.MaxFixedOrder;
|
//int max_fixed_order = m_settings.MaxFixedOrder;
|
||||||
int min_fixed_order = m_settings.MinFixedOrder;
|
//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 = m_settings.MaxPartitionOrder;
|
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;
|
||||||
m_settings.MinFixedOrder = 2;
|
//m_settings.MinFixedOrder = 2;
|
||||||
m_settings.MaxFixedOrder = 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;
|
||||||
m_settings.MaxLPCOrder = Math.Min(m_settings.MaxLPCOrder, Math.Max(m_settings.MinLPCOrder, 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, windows_mask);
|
||||||
m_settings.MinFixedOrder = min_fixed_order;
|
//m_settings.MinFixedOrder = min_fixed_order;
|
||||||
m_settings.MaxFixedOrder = max_fixed_order;
|
//m_settings.MaxFixedOrder = max_fixed_order;
|
||||||
m_settings.MaxLPCOrder = 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;
|
||||||
@@ -1408,36 +1749,140 @@ new int[] { // 30
|
|||||||
|
|
||||||
unsafe void encode_residual_pass2(FlacFrame frame, int ch)
|
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)
|
int* windows_present = stackalloc int[_windowcount];
|
||||||
return 0;
|
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)
|
switch (eparams.window_method)
|
||||||
{
|
{
|
||||||
case WindowMethod.Estimate:
|
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;
|
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[frame.subframes[ch].best.window];
|
||||||
double best_error = 0;
|
double err = lpc_ctx.prediction_error[frame.subframes[ch].best.order - 1] / lpc_ctx.autocorr_values[0];
|
||||||
int order = 2;
|
double est = frame.blocksize * (frame.subframes[ch].obits * (1 - err));
|
||||||
for (int i = 0; i < _windowcount; i++)
|
double est1 = frame.blocksize * (frame.subframes[ch].obits * (err));
|
||||||
{
|
if (est < 0 || est1 < 0) return -1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
#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:
|
case WindowMethod.Evaluate:
|
||||||
encode_residual_pass1(frame, ch, -1);
|
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:
|
case WindowMethod.Search:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1453,15 +1898,33 @@ new int[] { // 30
|
|||||||
case StereoMethod.Estimate:
|
case StereoMethod.Estimate:
|
||||||
for (int ch = 0; ch < subframes; ch++)
|
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];
|
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0];
|
||||||
lpc_ctx.GetReflection(4, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer);
|
int estimate_order = 4;
|
||||||
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, 4, 4.5, 0.0);
|
int iWindow = 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);
|
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;
|
break;
|
||||||
case StereoMethod.Evaluate:
|
case StereoMethod.Evaluate:
|
||||||
for (int ch = 0; ch < subframes; ch++)
|
for (int ch = 0; ch < subframes; ch++)
|
||||||
encode_residual_pass1(frame, ch, 0);
|
encode_residual_pass1(frame, ch, 1);
|
||||||
break;
|
break;
|
||||||
case StereoMethod.Search:
|
case StereoMethod.Search:
|
||||||
for (int ch = 0; ch < subframes; ch++)
|
for (int ch = 0; ch < subframes; ch++)
|
||||||
@@ -1538,11 +2001,18 @@ new int[] { // 30
|
|||||||
int sz = _windowsize;
|
int sz = _windowsize;
|
||||||
float* pos1 = window + _windowcount * Flake.MAX_BLOCKSIZE * 2;
|
float* pos1 = window + _windowcount * Flake.MAX_BLOCKSIZE * 2;
|
||||||
float* pos = pos1;
|
float* pos = pos1;
|
||||||
|
int nSeg = 0;
|
||||||
do
|
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);
|
func(pos, sz);
|
||||||
if ((sz & 1) != 0)
|
if ((sz & 1) != 0)
|
||||||
break;
|
break;
|
||||||
|
nSeg++;
|
||||||
pos += sz;
|
pos += sz;
|
||||||
sz >>= 1;
|
sz >>= 1;
|
||||||
} while (sz >= 32);
|
} while (sz >= 32);
|
||||||
@@ -1550,6 +2020,7 @@ new int[] { // 30
|
|||||||
for (int i = 0; i < _windowsize; i++)
|
for (int i = 0; i < _windowsize; i++)
|
||||||
scale += pos1[i] * pos1[i];
|
scale += pos1[i] * pos1[i];
|
||||||
windowScale[_windowcount] = scale;
|
windowScale[_windowcount] = scale;
|
||||||
|
windowType[_windowcount] = flag;
|
||||||
_windowcount++;
|
_windowcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1569,13 +2040,77 @@ new int[] { // 30
|
|||||||
calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
|
calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
|
||||||
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
|
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
|
||||||
calculate_window(window, lpc.window_bartlett, WindowFunction.Bartlett);
|
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)
|
if (_windowcount == 0)
|
||||||
throw new Exception("invalid windowfunction");
|
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)
|
if (channels != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent)
|
||||||
{
|
{
|
||||||
frame.window_buffer = window;
|
frame.window_buffer = window;
|
||||||
|
frame.nSeg = 0;
|
||||||
frame.current.residual = r + channels * Flake.MAX_BLOCKSIZE;
|
frame.current.residual = r + channels * Flake.MAX_BLOCKSIZE;
|
||||||
frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight;
|
frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight;
|
||||||
for (int ch = 0; ch < channels; ch++)
|
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);
|
//channel_decorrelation(s, s + Flake.MAX_BLOCKSIZE, s + 2 * Flake.MAX_BLOCKSIZE, s + 3 * Flake.MAX_BLOCKSIZE, frame.blocksize);
|
||||||
frame.window_buffer = window;
|
frame.window_buffer = window;
|
||||||
|
frame.nSeg = 0;
|
||||||
frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE;
|
frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE;
|
||||||
for (int ch = 0; ch < 4; ch++)
|
for (int ch = 0; ch < 4; ch++)
|
||||||
frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE,
|
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.InitSize(frame.blocksize / 2, true);
|
||||||
frame2.window_buffer = frame.window_buffer + frame.blocksize;
|
frame2.window_buffer = frame.window_buffer + frame.blocksize;
|
||||||
|
frame2.nSeg++;
|
||||||
frame2.current.residual = r + tumbler * 5 * Flake.MAX_BLOCKSIZE;
|
frame2.current.residual = r + tumbler * 5 * Flake.MAX_BLOCKSIZE;
|
||||||
for (int ch = 0; ch < 4; ch++)
|
for (int ch = 0; ch < 4; ch++)
|
||||||
frame2.subframes[ch].Init(frame.subframes[ch].samples, frame2.current.residual + (ch + 1) * frame2.blocksize,
|
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.InitSize(frame2.blocksize, true);
|
||||||
frame3.window_buffer = frame2.window_buffer;
|
frame3.window_buffer = frame2.window_buffer;
|
||||||
|
frame3.nSeg = frame2.nSeg;
|
||||||
frame3.current.residual = frame2.current.residual + 5 * frame2.blocksize;
|
frame3.current.residual = frame2.current.residual + 5 * frame2.blocksize;
|
||||||
for (int ch = 0; ch < 4; ch++)
|
for (int ch = 0; ch < 4; ch++)
|
||||||
frame3.subframes[ch].Init(frame2.subframes[ch].samples + frame2.blocksize, frame3.current.residual + (ch + 1) * frame3.blocksize,
|
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)
|
public int flake_set_defaults(FlakeWriterSettings settings)
|
||||||
{
|
{
|
||||||
// default to level 7 params
|
// default to level 7 params
|
||||||
window_function = WindowFunction.Flattop | WindowFunction.Tukey;
|
window_function = WindowFunction.PunchoutTukey | WindowFunction.PartialTukey | 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.EvaluateN;
|
||||||
block_time_ms = 105;
|
block_time_ms = 105;
|
||||||
prediction_type = PredictionType.Search;
|
prediction_type = PredictionType.Levinson;
|
||||||
estimation_depth = 1;
|
estimation_depth = 1;
|
||||||
variable_block_size = 0;
|
variable_block_size = 0;
|
||||||
lpc_min_precision_search = 1;
|
lpc_min_precision_search = 1;
|
||||||
@@ -2088,37 +2626,45 @@ new int[] { // 30
|
|||||||
switch (settings.EncoderModeIndex)
|
switch (settings.EncoderModeIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
block_time_ms = 53;
|
|
||||||
prediction_type = PredictionType.Fixed;
|
prediction_type = PredictionType.Fixed;
|
||||||
stereo_method = StereoMethod.Independent;
|
stereo_method = StereoMethod.Independent;
|
||||||
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.Tukey;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
prediction_type = PredictionType.Levinson;
|
prediction_type = PredictionType.Fixed;
|
||||||
stereo_method = StereoMethod.Independent;
|
stereo_method = StereoMethod.Independent;
|
||||||
window_function = WindowFunction.Bartlett;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.Tukey;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
stereo_method = StereoMethod.Independent;
|
stereo_method = StereoMethod.Estimate;
|
||||||
window_function = WindowFunction.Bartlett;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.PartialTukey;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
stereo_method = StereoMethod.Estimate;
|
stereo_method = StereoMethod.Estimate;
|
||||||
window_function = WindowFunction.Bartlett;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.PunchoutTukey;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
stereo_method = StereoMethod.Estimate;
|
stereo_method = StereoMethod.Estimate;
|
||||||
window_function = WindowFunction.Bartlett;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.PunchoutTukey;
|
||||||
|
estimation_depth = 2;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
stereo_method = StereoMethod.Estimate;
|
|
||||||
window_method = WindowMethod.Estimate;
|
window_method = WindowMethod.Estimate;
|
||||||
|
window_function = WindowFunction.PunchoutTukey;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
stereo_method = StereoMethod.Estimate;
|
window_method = WindowMethod.EstimateN;
|
||||||
|
window_function = WindowFunction.PunchoutTukey | WindowFunction.PartialTukey;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
|
prediction_type = PredictionType.Search;
|
||||||
estimation_depth = 2;
|
estimation_depth = 2;
|
||||||
lpc_min_precision_search = 0;
|
lpc_min_precision_search = 0;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
Independent = 0,
|
Independent = 0,
|
||||||
Estimate = 1,
|
Estimate = 1,
|
||||||
Evaluate = 2,
|
Evaluate = 2,
|
||||||
Search = 3
|
Search = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,17 @@
|
|||||||
{
|
{
|
||||||
public enum WindowFunction
|
public enum WindowFunction
|
||||||
{
|
{
|
||||||
|
None = 0,
|
||||||
Welch = 1,
|
Welch = 1,
|
||||||
Tukey = 2,
|
Tukey = 2,
|
||||||
Hann = 4,
|
Hann = 4,
|
||||||
Flattop = 8,
|
Flattop = 8,
|
||||||
Bartlett = 16,
|
Bartlett = 16,
|
||||||
TukeyFlattop = 10
|
TukeyFlattop = 10,
|
||||||
|
PartialTukey = 32,
|
||||||
|
TukeyPartialTukey = 34,
|
||||||
|
TukeyFlattopPartialTukey = 42,
|
||||||
|
PunchoutTukey = 64,
|
||||||
|
TukeyFlattopPartialTukeyPunchoutTukey = 106,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,16 @@
|
|||||||
{
|
{
|
||||||
public enum WindowMethod
|
public enum WindowMethod
|
||||||
{
|
{
|
||||||
Estimate = 0,
|
Evaluate,
|
||||||
Evaluate = 1,
|
Search,
|
||||||
Search = 2
|
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)]
|
[Browsable(false)]
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public AudioPCMConfig PCM
|
public AudioPCMConfig PCM
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ namespace CUETools.Codecs
|
|||||||
public class lpc
|
public class lpc
|
||||||
{
|
{
|
||||||
public const int MAX_LPC_ORDER = 32;
|
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_PRECISIONS = 4;
|
||||||
|
public const int MAX_LPC_SECTIONS = 32;
|
||||||
|
|
||||||
public unsafe static void window_welch(float* window, int L)
|
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)
|
public unsafe static void window_tukey(float* window, int L)
|
||||||
{
|
{
|
||||||
window_rectangle(window, L);
|
|
||||||
double p = 0.5;
|
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)
|
if (Np > 0)
|
||||||
{
|
{
|
||||||
for (int n = 0; n <= Np; n++)
|
for (int n = 0; n < z; n++)
|
||||||
{
|
window[n] = window[L - n - 1] = 0;
|
||||||
window[n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * n / Np));
|
for (int n = 0; n < Np - 1; n++)
|
||||||
window[L - Np - 1 + n] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * (n + Np) / Np));
|
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)
|
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);
|
return (short)((val >> 31) + ((val - 1) >> 31) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XXX
|
||||||
static public unsafe void
|
static public unsafe void
|
||||||
compute_corr_int(/*const*/ short* data1, short* data2, int len, int min, int lag, int* autoc)
|
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;
|
autoc[i] = temp + temp2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates autocorrelation data from audio samples
|
* Calculates autocorrelation data from audio samples
|
||||||
* A window function is applied before calculation.
|
* A window function is applied before calculation.
|
||||||
*/
|
*/
|
||||||
static public unsafe void
|
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
|
#if FPAC
|
||||||
short* data1 = stackalloc short[len + 1];
|
short* data1 = stackalloc short[len + 1];
|
||||||
@@ -125,29 +158,223 @@ namespace CUETools.Codecs
|
|||||||
for (int coeff = min; coeff <= lag; coeff++)
|
for (int coeff = min; coeff <= lag; coeff++)
|
||||||
autoc[coeff] = (c1[coeff] * (double)(1 << 18) + (c2[coeff] + c3[coeff]) * (double)(1 << 9) + c4[coeff]);
|
autoc[coeff] = (c1[coeff] * (double)(1 << 18) + (c2[coeff] + c3[coeff]) * (double)(1 << 9) + c4[coeff]);
|
||||||
#else
|
#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;
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < lag; i++)
|
||||||
|
data1[i] = prev != 0 ? data[i - lag] : 0;
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
data1[i] = data[i] * window[i];
|
data1[lag + i] = data[i] * window[i];
|
||||||
data1[len] = 0;
|
for (i = 0; i < lag; i++)
|
||||||
|
data1[lag + len + i] = next != 0 ? data[len + i] : 0;
|
||||||
|
|
||||||
for (i = min; i <= lag; ++i)
|
for (i = min; i <= lag; ++i)
|
||||||
{
|
{
|
||||||
double temp = 1.0;
|
double temp = 0;
|
||||||
double temp2 = 1.0;
|
double temp2 = 0;
|
||||||
double* finish = data1 + len - i;
|
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];
|
temp += pdata[i] * (*pdata++);
|
||||||
temp2 += pdata[i + 1] * pdata[1];
|
temp2 += pdata[i] * (*pdata++);
|
||||||
}
|
}
|
||||||
autoc[i] = temp + temp2;
|
if (pdata <= finish)
|
||||||
|
temp += pdata[i] * (*pdata++);
|
||||||
|
|
||||||
|
autoc[i] += temp + temp2;
|
||||||
}
|
}
|
||||||
#endif
|
#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.
|
* Levinson-Durbin recursion.
|
||||||
* Produces LPC coefficients from autocorrelation data.
|
* Produces LPC coefficients from autocorrelation data.
|
||||||
|
|||||||
@@ -1,7 +1,173 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace CUETools.Codecs
|
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>
|
/// <summary>
|
||||||
/// Context for LPC coefficients calculation and order estimation
|
/// Context for LPC coefficients calculation and order estimation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -36,18 +202,62 @@ namespace CUETools.Codecs
|
|||||||
/// <param name="samples">Samples pointer</param>
|
/// <param name="samples">Samples pointer</param>
|
||||||
/// <param name="blocksize">Block size</param>
|
/// <param name="blocksize">Block size</param>
|
||||||
/// <param name="window">Window function</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)
|
if (autocorr_order > order)
|
||||||
return;
|
return;
|
||||||
fixed (double* reff = reflection_coeffs, autoc = autocorr_values, err = prediction_error)
|
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);
|
lpc.compute_schur_reflection(autoc, (uint)order, reff, err);
|
||||||
autocorr_order = order + 1;
|
autocorr_order = order + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if XXX
|
||||||
public void GetReflection1(int order, int* samples, int blocksize, float* window)
|
public void GetReflection1(int order, int* samples, int blocksize, float* window)
|
||||||
{
|
{
|
||||||
if (autocorr_order > order)
|
if (autocorr_order > order)
|
||||||
@@ -83,11 +293,12 @@ namespace CUETools.Codecs
|
|||||||
autocorr_order = order + 1;
|
autocorr_order = order + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
public double Akaike(int blocksize, int order, double alpha, double beta)
|
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 - 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>
|
/// <summary>
|
||||||
|
|||||||
@@ -475,25 +475,45 @@ namespace CUETools.FlakeExe
|
|||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
|
settings = flake.Settings as FlakeWriterSettings;
|
||||||
Console.SetOut(stdout);
|
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.TotalSize,
|
||||||
flake.UserProcessorTime.TotalSeconds > 0 ? flake.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds,
|
flake.UserProcessorTime.TotalSeconds > 0 ? flake.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds,
|
||||||
flake.PredictionType.ToString().PadRight(15),
|
flake.PredictionType.ToString().PadRight(15),
|
||||||
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.WindowMethod.ToString().PadRight(10) + "(" +
|
||||||
(flake.Settings as FlakeWriterSettings).MinPartitionOrder,
|
((flake.WindowFunction & WindowFunction.Tukey) != 0 ? "T" : " ") +
|
||||||
(flake.Settings as FlakeWriterSettings).MaxPartitionOrder,
|
((flake.WindowFunction & WindowFunction.PartialTukey) != 0 ? "P" : " ") +
|
||||||
(flake.Settings as FlakeWriterSettings).MinLPCOrder,
|
(((flake.WindowFunction & WindowFunction.PunchoutTukey) != 0 ? "O" : "") +
|
||||||
(flake.Settings as FlakeWriterSettings).MaxLPCOrder,
|
((flake.WindowFunction & WindowFunction.Welch) == 0 ? "" : "W") +
|
||||||
(flake.Settings as FlakeWriterSettings).MinFixedOrder,
|
((flake.WindowFunction & WindowFunction.Hann) == 0 ? "" : "H") +
|
||||||
(flake.Settings as FlakeWriterSettings).MaxFixedOrder,
|
((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.MinPrecisionSearch,
|
||||||
flake.MaxPrecisionSearch,
|
flake.MaxPrecisionSearch,
|
||||||
flake.Settings.BlockSize,
|
flake.Settings.BlockSize,
|
||||||
flake.VBRMode,
|
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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user