Skip to content

Commit 51f6e39

Browse files
committed
Flake: use new window functions (partial_tukey, punchout_tukey).
1 parent 7039bc6 commit 51f6e39

File tree

15 files changed

+1314
-214
lines changed

15 files changed

+1314
-214
lines changed

CUETools.Codecs.ALAC/ALACSubframeInfo.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ unsafe class ALACSubframeInfo
66
public int* samples;
77
public uint done_fixed;
88
public LpcContext[] lpc_ctx;
9+
public LpcSubframeInfo sf;
910

1011
public ALACSubframeInfo()
1112
{
1213
best = new ALACSubframe();
13-
lpc_ctx = new LpcContext[Alac.MAX_LPC_WINDOWS];
14-
for (int i = 0; i < Alac.MAX_LPC_WINDOWS; i++)
14+
sf = new LpcSubframeInfo();
15+
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
16+
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
1517
lpc_ctx[i] = new LpcContext();
1618
}
1719

@@ -21,7 +23,8 @@ public void Init(int* s, int* r)
2123
best.residual = r;
2224
best.size = AudioSamples.UINT32_MAX;
2325
best.order = 0;
24-
for (int iWindow = 0; iWindow < Alac.MAX_LPC_WINDOWS; iWindow++)
26+
sf.Reset();
27+
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++)
2528
lpc_ctx[iWindow].Reset();
2629
done_fixed = 0;
2730
}

CUETools.Codecs.ALAC/ALACWriter.cs

+81-23
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace CUETools.Codecs.ALAC
3636
public class ALACWriterSettings: AudioEncoderSettings
3737
{
3838
public ALACWriterSettings()
39-
: base("0 1 2 3 4 5 6 7 8 9 10", "3")
39+
: base("0 1 2 3 4 5 6 7 8 9 10", "5")
4040
{
4141
}
4242

@@ -91,7 +91,8 @@ public class ALACWriter : IAudioDest
9191
int[] verifyBuffer;
9292
int[] residualBuffer;
9393
float[] windowBuffer;
94-
int samplesInBuffer = 0;
94+
LpcWindowSection[,] windowSections;
95+
int samplesInBuffer = 0;
9596

9697
int m_blockSize = 0;
9798
int _totalSize = 0;
@@ -122,7 +123,8 @@ public ALACWriter(string path, Stream IO, ALACWriterSettings settings)
122123

123124
samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (Settings.PCM.ChannelCount == 2 ? 5 : Settings.PCM.ChannelCount)];
124125
residualBuffer = new int[Alac.MAX_BLOCKSIZE * (Settings.PCM.ChannelCount == 2 ? 6 : Settings.PCM.ChannelCount + 1)];
125-
windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * Alac.MAX_LPC_WINDOWS];
126+
windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
127+
windowSections = new LpcWindowSection[lpc.MAX_LPC_WINDOWS, lpc.MAX_LPC_SECTIONS];
126128

127129
eparams.set_defaults(m_settings.EncoderModeIndex);
128130

@@ -875,7 +877,11 @@ unsafe void encode_residual(ALACFrame frame, int ch, int pass, int best_window)
875877

876878
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
877879

878-
lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2);
880+
fixed (LpcWindowSection* sections = &windowSections[iWindow, 0])
881+
lpc_ctx.GetReflection(
882+
frame.subframes[ch].sf, max_order, smp,
883+
frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2, sections,
884+
Settings.PCM.BitsPerSample * 2 + BitReader.log2i(frame.blocksize) >= 61);
879885
lpc_ctx.ComputeLPC(lpcs);
880886
lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, min_order, max_order, 5.0, 1.0/18);
881887
for (i = 0; i < eparams.estimation_depth && i < max_order; i++)
@@ -945,20 +951,36 @@ unsafe int estimate_best_window(ALACFrame frame, int ch)
945951
{
946952
case WindowMethod.Estimate:
947953
{
948-
int best_window = -1;
949-
double best_error = 0;
950-
int order = 2;
951-
for (int i = 0; i < _windowcount; i++)
954+
int order = 4;
955+
float* err = stackalloc float[lpc.MAX_LPC_ORDER];
956+
for (int i = 0; i < _windowcount; i++)
952957
{
953-
frame.subframes[ch].lpc_ctx[i].GetReflection(order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + i * Alac.MAX_BLOCKSIZE * 2);
954-
double err = frame.subframes[ch].lpc_ctx[i].prediction_error[order - 1] / frame.subframes[ch].lpc_ctx[i].autocorr_values[0];
955-
if (best_window == -1 || best_error > err)
956-
{
957-
best_window = i;
958-
best_error = err;
959-
}
958+
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[i];
959+
fixed (LpcWindowSection* sections = &windowSections[i, 0])
960+
lpc_ctx.GetReflection(
961+
frame.subframes[ch].sf, order,
962+
frame.subframes[ch].samples,
963+
frame.window_buffer + i * Alac.MAX_BLOCKSIZE * 2, sections,
964+
Settings.PCM.BitsPerSample * 2 + BitReader.log2i(frame.blocksize) >= 61);
965+
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, order, 4.5, 0.0);
966+
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);
960967
}
961-
return best_window;
968+
int* best_windows = stackalloc int[lpc.MAX_LPC_ORDER];
969+
for (int i = 0; i < _windowcount; i++)
970+
best_windows[i] = i;
971+
for (int i = 0; i < _windowcount; i++)
972+
{
973+
for (int j = i + 1; j < _windowcount; j++)
974+
{
975+
if (err[best_windows[i]] > err[best_windows[j]])
976+
{
977+
int tmp = best_windows[j];
978+
best_windows[j] = best_windows[i];
979+
best_windows[i] = tmp;
980+
}
981+
}
982+
}
983+
return best_windows[0];
962984
}
963985
case WindowMethod.Evaluate:
964986
encode_residual_pass1(frame, ch, -1);
@@ -978,10 +1000,16 @@ unsafe void estimate_frame(ALACFrame frame, bool do_midside)
9781000
case StereoMethod.Estimate:
9791001
for (int ch = 0; ch < subframes; ch++)
9801002
{
981-
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0];
982-
int stereo_order = Math.Min(8, eparams.max_prediction_order);
1003+
int iWindow = 0;
1004+
LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];
1005+
int stereo_order = Math.Min(8, eparams.max_prediction_order);
9831006
double alpha = 1.5; // 4.5 + eparams.max_prediction_order / 10.0;
984-
lpc_ctx.GetReflection(stereo_order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer);
1007+
fixed (LpcWindowSection* sections = &windowSections[iWindow, 0])
1008+
lpc_ctx.GetReflection(
1009+
frame.subframes[ch].sf, stereo_order,
1010+
frame.subframes[ch].samples,
1011+
frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2, sections,
1012+
Settings.PCM.BitsPerSample * 2 + BitReader.log2i(frame.blocksize) >= 61);
9851013
lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, stereo_order, alpha, 0);
9861014
frame.subframes[ch].best.size = (uint)Math.Max(0, lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], alpha, 0));
9871015
}
@@ -1060,13 +1088,17 @@ unsafe void encode_estimated_frame(ALACFrame frame)
10601088

10611089
unsafe void calculate_window(float * window, window_function func, WindowFunction flag)
10621090
{
1063-
if ((eparams.window_function & flag) == 0 || _windowcount == Alac.MAX_LPC_WINDOWS)
1091+
if ((eparams.window_function & flag) == 0 || _windowcount == lpc.MAX_LPC_WINDOWS)
10641092
return;
10651093
int sz = _windowsize;
10661094
float* pos = window + _windowcount * Alac.MAX_BLOCKSIZE * 2;
10671095
do
10681096
{
1069-
func(pos, sz);
1097+
windowSections[_windowcount, 0].setData(0, sz);
1098+
for (int j = 1; j < lpc.MAX_LPC_SECTIONS; j++)
1099+
windowSections[_windowcount, j].setZero(sz, sz);
1100+
func(pos, sz);
1101+
break;
10701102
if ((sz & 1) != 0)
10711103
break;
10721104
pos += sz;
@@ -1091,9 +1123,33 @@ unsafe int encode_frame(ref int size)
10911123
calculate_window(window, lpc.window_tukey, WindowFunction.Tukey);
10921124
calculate_window(window, lpc.window_hann, WindowFunction.Hann);
10931125
calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
1094-
if (_windowcount == 0)
1126+
int tukey_parts = 2;
1127+
double overlap = -0.3;
1128+
double overlap_units = overlap / (1.0 - overlap);
1129+
for (int m = 0; m < tukey_parts; m++)
1130+
calculate_window(window, (w, wsz) =>
1131+
{
1132+
lpc.window_punchout_tukey(w, wsz, 0.1,
1133+
m / (tukey_parts + overlap_units),
1134+
(m + 1 + overlap_units) / (tukey_parts + overlap_units));
1135+
}, WindowFunction.PartialTukey);
1136+
1137+
tukey_parts = 3;
1138+
overlap = -0.1;
1139+
//overlap = 0.1;
1140+
overlap_units = overlap / (1.0 - overlap);
1141+
for (int m = 0; m < tukey_parts; m++)
1142+
calculate_window(window, (w, wsz) =>
1143+
{
1144+
lpc.window_punchout_tukey(w, wsz, 0.1,
1145+
m / (tukey_parts + overlap_units),
1146+
(m + 1 + overlap_units) / (tukey_parts + overlap_units));
1147+
}, WindowFunction.PunchoutTukey);
1148+
if (_windowcount == 0)
10951149
throw new Exception("invalid windowfunction");
1096-
}
1150+
fixed (LpcWindowSection* sections = &windowSections[0, 0])
1151+
LpcWindowSection.Detect(_windowcount, window, Alac.MAX_BLOCKSIZE * 2, _windowsize, sections);
1152+
}
10971153
frame.window_buffer = window;
10981154

10991155
int bps = Settings.PCM.BitsPerSample + Settings.PCM.ChannelCount - 1;
@@ -1793,11 +1849,13 @@ public int set_defaults(int lvl)
17931849
case 4:
17941850
stereo_method = StereoMethod.Estimate;
17951851
window_method = WindowMethod.Estimate;
1852+
window_function = WindowFunction.PartialTukey | WindowFunction.PunchoutTukey;
17961853
max_prediction_order = 8;
17971854
break;
17981855
case 5:
17991856
stereo_method = StereoMethod.Estimate;
18001857
window_method = WindowMethod.Estimate;
1858+
window_function = WindowFunction.PartialTukey | WindowFunction.PunchoutTukey;
18011859
break;
18021860
case 6:
18031861
stereo_method = StereoMethod.Estimate;

CUETools.Codecs.ALAC/Alac.cs

-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public class Alac
2828
public const int MAX_RICE_PARAM = 14;
2929
public const int MAX_PARTITION_ORDER = 8;
3030
public const int MAX_PARTITIONS = 1 << MAX_PARTITION_ORDER;
31-
public const int MAX_LPC_WINDOWS = 4;
3231

3332
public const uint UINT32_MAX = 0xffffffff;
3433

CUETools.Codecs.ALAC/WindowFunction.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public enum WindowFunction
77
Hann = 4,
88
Flattop = 8,
99
Bartlett = 16,
10-
TukFlat = 10
10+
TukFlat = 10,
11+
PartialTukey = 32,
12+
PunchoutTukey = 64,
1113
}
1214
}

CUETools.Codecs.FLACCL/FLACCLWriter.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ public class FLACCLWriter : IAudioDest
270270
string _path;
271271
long _position;
272272

273+
public const int MAX_LPC_WINDOWS = 2;
274+
273275
// number of audio channels
274276
// valid values are 1 to 8
275277
int channels, ch_code;
@@ -1090,7 +1092,7 @@ void output_frame_footer(FlacFrame frame)
10901092

10911093
unsafe void calculate_window(FLACCLTask task, window_function func, WindowFunction flag)
10921094
{
1093-
if ((eparams.window_function & flag) == 0 || task.nWindowFunctions == lpc.MAX_LPC_WINDOWS)
1095+
if ((eparams.window_function & flag) == 0 || task.nWindowFunctions == MAX_LPC_WINDOWS)
10941096
return;
10951097

10961098
func(((float*)task.clWindowFunctionsPtr) + task.nWindowFunctions * task.frameSize, task.frameSize);
@@ -2508,10 +2510,10 @@ unsafe public FLACCLTask(CLProgram _openCLProgram, int channelsCount, int max_fr
25082510
int residualBufferLen = sizeof(int) * MAX_CHANNELSIZE * channels; // need to adjust residualOffset?
25092511
int partitionsLen = sizeof(int) * ((writer.Settings.PCM.BitsPerSample > 16 ? 31 : 15) * 2 << 8) * channels * MAX_FRAMES;
25102512
int riceParamsLen = sizeof(int) * (4 << 8) * channels * MAX_FRAMES;
2511-
int autocorLen = sizeof(float) * (MAX_ORDER + 1) * lpc.MAX_LPC_WINDOWS * channelsCount * MAX_FRAMES;
2513+
int autocorLen = sizeof(float) * (MAX_ORDER + 1) * FLACCLWriter.MAX_LPC_WINDOWS * channelsCount * MAX_FRAMES;
25122514
int lpcDataLen = autocorLen * 32;
2513-
int resOutLen = sizeof(int) * channelsCount * (lpc.MAX_LPC_WINDOWS * lpc.MAX_LPC_ORDER + 8) * MAX_FRAMES;
2514-
int wndLen = sizeof(float) * MAX_CHANNELSIZE /** 2*/ * lpc.MAX_LPC_WINDOWS;
2515+
int resOutLen = sizeof(int) * channelsCount * (FLACCLWriter.MAX_LPC_WINDOWS * lpc.MAX_LPC_ORDER + 8) * MAX_FRAMES;
2516+
int wndLen = sizeof(float) * MAX_CHANNELSIZE /** 2*/ * FLACCLWriter.MAX_LPC_WINDOWS;
25152517
int selectedLen = sizeof(int) * 32 * channelsCount * MAX_FRAMES;
25162518
int riceLen = sizeof(int) * channels * MAX_CHANNELSIZE;
25172519

CUETools.Codecs.FLAKE/FlacFrame.cs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ unsafe public class FlacFrame
1111
public int frame_number;
1212
public FlacSubframe current;
1313
public float* window_buffer;
14+
public int nSeg = 0;
1415

1516
public BitWriter writer = null;
1617
public int writer_offset = 0;

CUETools.Codecs.FLAKE/FlacSubframeInfo.cs

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ unsafe public class FlacSubframeInfo
77
public FlacSubframeInfo()
88
{
99
best = new FlacSubframe();
10+
sf = new LpcSubframeInfo();
1011
lpc_ctx = new LpcContext[lpc.MAX_LPC_WINDOWS];
1112
for (int i = 0; i < lpc.MAX_LPC_WINDOWS; i++)
1213
lpc_ctx[i] = new LpcContext();
@@ -22,8 +23,10 @@ public void Init(int* s, int* r, int bps, int w)
2223
best.residual = r;
2324
best.type = SubframeType.Verbatim;
2425
best.size = AudioSamples.UINT32_MAX;
26+
sf.Reset();
2527
for (int iWindow = 0; iWindow < lpc.MAX_LPC_WINDOWS; iWindow++)
2628
lpc_ctx[iWindow].Reset();
29+
//sf.obits = obits;
2730
done_fixed = 0;
2831
}
2932

@@ -33,5 +36,6 @@ public void Init(int* s, int* r, int bps, int w)
3336
public int* samples;
3437
public uint done_fixed;
3538
public LpcContext[] lpc_ctx;
39+
public LpcSubframeInfo sf;
3640
};
3741
}

0 commit comments

Comments
 (0)