@@ -27,7 +27,8 @@ const FLAG_STEREO: u8 = 1 << 5;
2727const INSTRUMENT_SIZE : u32 = 263 ;
2828const MINIMUM_INSTRUMENT_SIZE : u32 = 29 ;
2929
30- const PADDING_LIMIT : u32 = 2 * 1024 * 1024 ;
30+ const PADDING_LIMIT : u32 = 44100 * 10 ; // TODO
31+
3132const ADPCM_COMPRESSION_TABLE_SIZE : u32 = 16 ;
3233
3334/// Determine if given bytes could be an Extended Module.
@@ -187,7 +188,7 @@ pub fn load(buffer: Vec<u8>, source: Option<PathBuf>) -> Result<Module, Error> {
187188 // See: Page 16 in "The Unofficial XM File Format Specification"
188189 let length_bytes = match smp. pcm_type == PcmType :: ADPCM {
189190 true => ADPCM_COMPRESSION_TABLE_SIZE + ( ( smp. length + 1 ) / 2 ) ,
190- _ => smp. length ,
191+ false => smp. length ,
191192 } ;
192193
193194 // Apparently, it is common for samples to report their sizes beyond what the file can store.
@@ -198,25 +199,29 @@ pub fn load(buffer: Vec<u8>, source: Option<PathBuf>) -> Result<Module, Error> {
198199 //
199200 // We need to add extra padding as loop points may point to them.
200201 if smp. pointer + length_bytes > buffer. len ( ) as u32 {
201- extra_padding = buffer. len ( ) as u32 - smp. pointer + length_bytes;
202- samples. push ( smp) ;
202+ extra_padding = ( smp. pointer + length_bytes) - buffer. len ( ) as u32 ;
203+
204+ if extra_padding < PADDING_LIMIT {
205+ samples. push ( smp) ;
206+ }
203207
204208 break ' parse_instrument;
205209 }
206210
207211 file. skip_bytes ( length_bytes as i64 ) ?;
208-
209212 samples. push ( smp) ;
210213 }
211214 }
212215
216+ sanity_check_samples ( & mut samples) ;
217+
213218 samples
214219 } ;
215220
216221 let mut buffer = buffer;
217222
218223 if extra_padding > 0 {
219- let new_len = buffer. len ( ) + extra_padding. clamp ( 0 , PADDING_LIMIT ) as usize ;
224+ let new_len = buffer. len ( ) + extra_padding as usize ;
220225 buffer. resize ( new_len, 0 ) ;
221226 info ! ( "Padded last sample with {} extra bytes" , extra_padding) ;
222227 }
@@ -232,3 +237,19 @@ pub fn load(buffer: Vec<u8>, source: Option<PathBuf>) -> Result<Module, Error> {
232237 samples : samples. into ( ) ,
233238 } )
234239}
240+
241+ /// HACK: Removes some really cursed samples. I really need a better heuristic.
242+ /// For "xenia3.xm", xmodits reports last sample to be 5Hz and has a duration of ~34.5 hours.
243+ fn sanity_check_samples ( samples : & mut Vec < Sample > ) {
244+ use std:: time:: Duration ;
245+
246+ samples. retain ( |smp| {
247+ let less_than_15_mins =
248+ Duration :: from_secs_f32 ( smp. length_frames ( ) as f32 / smp. rate as f32 )
249+ < Duration :: from_secs ( 60 * 15 ) ;
250+
251+ let sensible_sample_rate = ( 256 ..=384_000 ) . contains ( & smp. rate ) ;
252+
253+ sensible_sample_rate && less_than_15_mins
254+ } )
255+ }
0 commit comments