From 5604778455e5fc10db4c08c6a7fa6da540703ccc Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 7 Dec 2016 18:34:31 -0500 Subject: [PATCH] Fix audio data extraction The audio data was initially read and written by chunks of 2352 bytes, which is the usual sector size for audio CDs. However, this didn't work on images with a 2448-byte sector size (2352 bytes data + 96 bytes sub-channel data): we would end up reading data from the NRG footer. The data is now read/written by 4 MiB (which is faster anyway), and we make sure to read the remaining bytes if the audio data size is not a multiple of 4 MiB. --- src/raw_audio.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/raw_audio.rs b/src/raw_audio.rs index c02b7ef..9c98357 100644 --- a/src/raw_audio.rs +++ b/src/raw_audio.rs @@ -41,6 +41,8 @@ pub fn extract_nrg_raw_audio(in_fd: &mut File, img_path: &String, metadata: &NrgMetadata) -> Result<(), NrgError> { + const BUF_SIZE: usize = 1024 * 1024 * 4; // 4 MiB + // Seek to the first audio byte let skip_bytes = get_daox_track1_index1(metadata); try!(in_fd.seek(SeekFrom::Start(skip_bytes))); @@ -51,21 +53,34 @@ pub fn extract_nrg_raw_audio(in_fd: &mut File, // Read/write audio data let mut cur_offset = skip_bytes; - while cur_offset < metadata.chunk_offset { - let mut audio_buf = [0u8; 2352]; + while cur_offset + BUF_SIZE as u64 <= metadata.chunk_offset { + let mut audio_buf = [0u8; BUF_SIZE]; let mut nbytes = try!(in_fd.read(&mut audio_buf)); - if nbytes != 2352 { + if nbytes != BUF_SIZE { return Err(NrgError::AudioReadError); } cur_offset += nbytes as u64; nbytes = try!(out_fd.write(&audio_buf)); - if nbytes != 2352 { + if nbytes != BUF_SIZE { return Err(NrgError::AudioWriteError); } } + // Read/write the last bytes + let remaining: usize = (metadata.chunk_offset - cur_offset) as usize; + let mut audio_buf = vec![0u8; remaining]; + let mut nbytes = try!(in_fd.read(&mut audio_buf)); + if nbytes != remaining { + return Err(NrgError::AudioReadError); + } + cur_offset += nbytes as u64; + nbytes = try!(out_fd.write(&audio_buf)); + if nbytes != remaining { + return Err(NrgError::AudioWriteError); + } + assert_eq!(cur_offset, metadata.chunk_offset); Ok(()) }