@@ -36,7 +36,7 @@ namespace CUETools.Codecs.ALAC
36
36
public class ALACWriterSettings : AudioEncoderSettings
37
37
{
38
38
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 " )
40
40
{
41
41
}
42
42
@@ -91,7 +91,8 @@ public class ALACWriter : IAudioDest
91
91
int [ ] verifyBuffer ;
92
92
int [ ] residualBuffer ;
93
93
float [ ] windowBuffer ;
94
- int samplesInBuffer = 0 ;
94
+ LpcWindowSection [ , ] windowSections ;
95
+ int samplesInBuffer = 0 ;
95
96
96
97
int m_blockSize = 0 ;
97
98
int _totalSize = 0 ;
@@ -122,7 +123,8 @@ public ALACWriter(string path, Stream IO, ALACWriterSettings settings)
122
123
123
124
samplesBuffer = new int [ Alac . MAX_BLOCKSIZE * ( Settings . PCM . ChannelCount == 2 ? 5 : Settings . PCM . ChannelCount ) ] ;
124
125
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 ] ;
126
128
127
129
eparams . set_defaults ( m_settings . EncoderModeIndex ) ;
128
130
@@ -875,7 +877,11 @@ unsafe void encode_residual(ALACFrame frame, int ch, int pass, int best_window)
875
877
876
878
LpcContext lpc_ctx = frame . subframes [ ch ] . lpc_ctx [ iWindow ] ;
877
879
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 ) ;
879
885
lpc_ctx . ComputeLPC ( lpcs ) ;
880
886
lpc_ctx . SortOrdersAkaike ( frame . blocksize , eparams . estimation_depth , min_order , max_order , 5.0 , 1.0 / 18 ) ;
881
887
for ( i = 0 ; i < eparams . estimation_depth && i < max_order ; i ++ )
@@ -945,20 +951,36 @@ unsafe int estimate_best_window(ALACFrame frame, int ch)
945
951
{
946
952
case WindowMethod . Estimate :
947
953
{
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 ++ )
952
957
{
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 ) ;
960
967
}
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 ] ;
962
984
}
963
985
case WindowMethod . Evaluate :
964
986
encode_residual_pass1 ( frame , ch , - 1 ) ;
@@ -978,10 +1000,16 @@ unsafe void estimate_frame(ALACFrame frame, bool do_midside)
978
1000
case StereoMethod . Estimate :
979
1001
for ( int ch = 0 ; ch < subframes ; ch ++ )
980
1002
{
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 ) ;
983
1006
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 ) ;
985
1013
lpc_ctx . SortOrdersAkaike ( frame . blocksize , 1 , 1 , stereo_order , alpha , 0 ) ;
986
1014
frame . subframes [ ch ] . best . size = ( uint ) Math . Max ( 0 , lpc_ctx . Akaike ( frame . blocksize , lpc_ctx . best_orders [ 0 ] , alpha , 0 ) ) ;
987
1015
}
@@ -1060,13 +1088,17 @@ unsafe void encode_estimated_frame(ALACFrame frame)
1060
1088
1061
1089
unsafe void calculate_window ( float * window , window_function func , WindowFunction flag )
1062
1090
{
1063
- if ( ( eparams . window_function & flag ) == 0 || _windowcount == Alac . MAX_LPC_WINDOWS )
1091
+ if ( ( eparams . window_function & flag ) == 0 || _windowcount == lpc . MAX_LPC_WINDOWS )
1064
1092
return ;
1065
1093
int sz = _windowsize ;
1066
1094
float * pos = window + _windowcount * Alac . MAX_BLOCKSIZE * 2 ;
1067
1095
do
1068
1096
{
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 ;
1070
1102
if ( ( sz & 1 ) != 0 )
1071
1103
break ;
1072
1104
pos += sz ;
@@ -1091,9 +1123,33 @@ unsafe int encode_frame(ref int size)
1091
1123
calculate_window ( window , lpc . window_tukey , WindowFunction . Tukey ) ;
1092
1124
calculate_window ( window , lpc . window_hann , WindowFunction . Hann ) ;
1093
1125
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 )
1095
1149
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
+ }
1097
1153
frame . window_buffer = window ;
1098
1154
1099
1155
int bps = Settings . PCM . BitsPerSample + Settings . PCM . ChannelCount - 1 ;
@@ -1793,11 +1849,13 @@ public int set_defaults(int lvl)
1793
1849
case 4 :
1794
1850
stereo_method = StereoMethod . Estimate ;
1795
1851
window_method = WindowMethod . Estimate ;
1852
+ window_function = WindowFunction . PartialTukey | WindowFunction . PunchoutTukey ;
1796
1853
max_prediction_order = 8 ;
1797
1854
break ;
1798
1855
case 5 :
1799
1856
stereo_method = StereoMethod . Estimate ;
1800
1857
window_method = WindowMethod . Estimate ;
1858
+ window_function = WindowFunction . PartialTukey | WindowFunction . PunchoutTukey ;
1801
1859
break ;
1802
1860
case 6 :
1803
1861
stereo_method = StereoMethod . Estimate ;
0 commit comments