pub struct ApeDecoder<R: Read + Seek> { /* private fields */ }Expand description
A streaming APE decoder with seek support.
Implementations§
Source§impl<R: Read + Seek> ApeDecoder<R>
impl<R: Read + Seek> ApeDecoder<R>
Sourcepub fn new(reader: R) -> ApeResult<Self>
pub fn new(reader: R) -> ApeResult<Self>
Open an APE file and parse its header.
Examples found in repository?
8fn main() {
9 let path = std::env::args().nth(1).expect("Usage: decode <file.ape>");
10 let file = File::open(&path).expect("failed to open file");
11 let mut decoder =
12 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
13
14 let info = decoder.info();
15 println!(
16 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
17 info.sample_rate, info.channels, info.bits_per_sample, info.total_samples, info.duration_ms,
18 );
19
20 let pcm = decoder.decode_all().expect("failed to decode");
21 println!("Decoded {} bytes of PCM", pcm.len());
22}More examples
9fn main() {
10 let args: Vec<String> = std::env::args().collect();
11
12 let (raw_mode, input, output) = if args.len() == 4 && args[1] == "--raw" {
13 (true, &args[2], &args[3])
14 } else if args.len() == 3 {
15 (false, &args[1], &args[2])
16 } else {
17 eprintln!("Usage: decode_to_file [--raw] <input.ape> <output>");
18 std::process::exit(1);
19 };
20
21 let file = File::open(input).expect("failed to open input file");
22 let mut decoder =
23 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
24
25 {
26 let info = decoder.info();
27 eprintln!(
28 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
29 info.sample_rate,
30 info.channels,
31 info.bits_per_sample,
32 info.total_samples,
33 info.duration_ms,
34 );
35 }
36
37 let pcm = decoder.decode_all().expect("failed to decode");
38 eprintln!("Decoded {} bytes of PCM", pcm.len());
39
40 let mut out = File::create(output).expect("failed to create output file");
41
42 if !raw_mode {
43 // Write WAV header: prefer stored header from the APE file, fall back to generated
44 let header = decoder
45 .wav_header_data()
46 .map(|h| h.to_vec())
47 .unwrap_or_else(|| decoder.info().generate_wav_header());
48 out.write_all(&header).expect("failed to write WAV header");
49 }
50
51 out.write_all(&pcm).expect("failed to write PCM data");
52 eprintln!("Wrote {}", output);
53}Sourcepub fn info(&self) -> &ApeInfo
pub fn info(&self) -> &ApeInfo
Get file metadata.
Examples found in repository?
8fn main() {
9 let path = std::env::args().nth(1).expect("Usage: decode <file.ape>");
10 let file = File::open(&path).expect("failed to open file");
11 let mut decoder =
12 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
13
14 let info = decoder.info();
15 println!(
16 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
17 info.sample_rate, info.channels, info.bits_per_sample, info.total_samples, info.duration_ms,
18 );
19
20 let pcm = decoder.decode_all().expect("failed to decode");
21 println!("Decoded {} bytes of PCM", pcm.len());
22}More examples
9fn main() {
10 let args: Vec<String> = std::env::args().collect();
11
12 let (raw_mode, input, output) = if args.len() == 4 && args[1] == "--raw" {
13 (true, &args[2], &args[3])
14 } else if args.len() == 3 {
15 (false, &args[1], &args[2])
16 } else {
17 eprintln!("Usage: decode_to_file [--raw] <input.ape> <output>");
18 std::process::exit(1);
19 };
20
21 let file = File::open(input).expect("failed to open input file");
22 let mut decoder =
23 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
24
25 {
26 let info = decoder.info();
27 eprintln!(
28 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
29 info.sample_rate,
30 info.channels,
31 info.bits_per_sample,
32 info.total_samples,
33 info.duration_ms,
34 );
35 }
36
37 let pcm = decoder.decode_all().expect("failed to decode");
38 eprintln!("Decoded {} bytes of PCM", pcm.len());
39
40 let mut out = File::create(output).expect("failed to create output file");
41
42 if !raw_mode {
43 // Write WAV header: prefer stored header from the APE file, fall back to generated
44 let header = decoder
45 .wav_header_data()
46 .map(|h| h.to_vec())
47 .unwrap_or_else(|| decoder.info().generate_wav_header());
48 out.write_all(&header).expect("failed to write WAV header");
49 }
50
51 out.write_all(&pcm).expect("failed to write PCM data");
52 eprintln!("Wrote {}", output);
53}Sourcepub fn total_frames(&self) -> u32
pub fn total_frames(&self) -> u32
Total number of frames in the file.
Sourcepub fn decode_frame(&mut self, frame_idx: u32) -> ApeResult<Vec<u8>>
pub fn decode_frame(&mut self, frame_idx: u32) -> ApeResult<Vec<u8>>
Decode a single frame by index, returning raw PCM bytes.
Sourcepub fn decode_all(&mut self) -> ApeResult<Vec<u8>>
pub fn decode_all(&mut self) -> ApeResult<Vec<u8>>
Decode all frames, returning all PCM bytes.
Examples found in repository?
8fn main() {
9 let path = std::env::args().nth(1).expect("Usage: decode <file.ape>");
10 let file = File::open(&path).expect("failed to open file");
11 let mut decoder =
12 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
13
14 let info = decoder.info();
15 println!(
16 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
17 info.sample_rate, info.channels, info.bits_per_sample, info.total_samples, info.duration_ms,
18 );
19
20 let pcm = decoder.decode_all().expect("failed to decode");
21 println!("Decoded {} bytes of PCM", pcm.len());
22}More examples
9fn main() {
10 let args: Vec<String> = std::env::args().collect();
11
12 let (raw_mode, input, output) = if args.len() == 4 && args[1] == "--raw" {
13 (true, &args[2], &args[3])
14 } else if args.len() == 3 {
15 (false, &args[1], &args[2])
16 } else {
17 eprintln!("Usage: decode_to_file [--raw] <input.ape> <output>");
18 std::process::exit(1);
19 };
20
21 let file = File::open(input).expect("failed to open input file");
22 let mut decoder =
23 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
24
25 {
26 let info = decoder.info();
27 eprintln!(
28 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
29 info.sample_rate,
30 info.channels,
31 info.bits_per_sample,
32 info.total_samples,
33 info.duration_ms,
34 );
35 }
36
37 let pcm = decoder.decode_all().expect("failed to decode");
38 eprintln!("Decoded {} bytes of PCM", pcm.len());
39
40 let mut out = File::create(output).expect("failed to create output file");
41
42 if !raw_mode {
43 // Write WAV header: prefer stored header from the APE file, fall back to generated
44 let header = decoder
45 .wav_header_data()
46 .map(|h| h.to_vec())
47 .unwrap_or_else(|| decoder.info().generate_wav_header());
48 out.write_all(&header).expect("failed to write WAV header");
49 }
50
51 out.write_all(&pcm).expect("failed to write PCM data");
52 eprintln!("Wrote {}", output);
53}Sourcepub fn decode_all_with<F: FnMut(f64) -> bool>(
&mut self,
on_progress: F,
) -> ApeResult<Vec<u8>>
pub fn decode_all_with<F: FnMut(f64) -> bool>( &mut self, on_progress: F, ) -> ApeResult<Vec<u8>>
Decode all frames with a progress closure.
The closure receives a progress fraction (0.0 to 1.0) after each frame.
Return true to continue, false to cancel decoding.
Sourcepub fn decode_all_parallel(&mut self, thread_count: usize) -> ApeResult<Vec<u8>>
pub fn decode_all_parallel(&mut self, thread_count: usize) -> ApeResult<Vec<u8>>
Decode all frames using multiple threads for parallel decoding.
Frame data is read sequentially (IO is serial), but frame decoding runs
in parallel across thread_count threads. Falls back to single-threaded
if thread_count <= 1.
Output is byte-identical to decode_all().
Sourcepub fn decode_range(
&mut self,
start_sample: u64,
end_sample: u64,
) -> ApeResult<Vec<u8>>
pub fn decode_range( &mut self, start_sample: u64, end_sample: u64, ) -> ApeResult<Vec<u8>>
Decode a sample range, returning only the PCM bytes within
start_sample..end_sample (exclusive end).
This is more efficient than decode_all() for extracting a portion of a file,
as it only decodes the frames that overlap the requested range.
Sourcepub fn seek(&mut self, sample: u64) -> ApeResult<SeekResult>
pub fn seek(&mut self, sample: u64) -> ApeResult<SeekResult>
Seek to a specific sample position. Returns a SeekResult with the
frame index, number of samples to skip within that frame, and the
exact sample position.
Sourcepub fn decode_from(&mut self, sample: u64) -> ApeResult<Vec<u8>>
pub fn decode_from(&mut self, sample: u64) -> ApeResult<Vec<u8>>
Seek to a sample position and return PCM from that point to the end of the containing frame.
Sourcepub fn wav_header_data(&self) -> Option<&[u8]>
pub fn wav_header_data(&self) -> Option<&[u8]>
Get the original WAV header data stored in the APE file.
Returns None if the CREATE_WAV_HEADER flag is set (header not stored).
Examples found in repository?
9fn main() {
10 let args: Vec<String> = std::env::args().collect();
11
12 let (raw_mode, input, output) = if args.len() == 4 && args[1] == "--raw" {
13 (true, &args[2], &args[3])
14 } else if args.len() == 3 {
15 (false, &args[1], &args[2])
16 } else {
17 eprintln!("Usage: decode_to_file [--raw] <input.ape> <output>");
18 std::process::exit(1);
19 };
20
21 let file = File::open(input).expect("failed to open input file");
22 let mut decoder =
23 ape_decoder::ApeDecoder::new(BufReader::new(file)).expect("failed to parse APE");
24
25 {
26 let info = decoder.info();
27 eprintln!(
28 "{}Hz, {} ch, {}-bit, {} samples ({} ms)",
29 info.sample_rate,
30 info.channels,
31 info.bits_per_sample,
32 info.total_samples,
33 info.duration_ms,
34 );
35 }
36
37 let pcm = decoder.decode_all().expect("failed to decode");
38 eprintln!("Decoded {} bytes of PCM", pcm.len());
39
40 let mut out = File::create(output).expect("failed to create output file");
41
42 if !raw_mode {
43 // Write WAV header: prefer stored header from the APE file, fall back to generated
44 let header = decoder
45 .wav_header_data()
46 .map(|h| h.to_vec())
47 .unwrap_or_else(|| decoder.info().generate_wav_header());
48 out.write_all(&header).expect("failed to write WAV header");
49 }
50
51 out.write_all(&pcm).expect("failed to write PCM data");
52 eprintln!("Wrote {}", output);
53}Sourcepub fn wav_terminating_bytes(&self) -> u32
pub fn wav_terminating_bytes(&self) -> u32
Get the number of terminating data bytes from the original container.
Sourcepub fn read_tag(&mut self) -> ApeResult<Option<ApeTag>>
pub fn read_tag(&mut self) -> ApeResult<Option<ApeTag>>
Read and parse APE tags from the file (APEv2 format).
Returns None if no tag is present.
Sourcepub fn read_id3v2_tag(&mut self) -> ApeResult<Option<Id3v2Tag>>
pub fn read_id3v2_tag(&mut self) -> ApeResult<Option<Id3v2Tag>>
Read and parse an ID3v2 tag from the beginning of the file.
Returns None if no ID3v2 header is present.
Sourcepub fn stored_md5(&self) -> &[u8; 16]
pub fn stored_md5(&self) -> &[u8; 16]
Get the stored MD5 hash from the APE descriptor.
Sourcepub fn verify_md5(&mut self) -> ApeResult<bool>
pub fn verify_md5(&mut self) -> ApeResult<bool>
Quick verify: compute MD5 over raw file sections and compare against
the stored hash in the APE descriptor. Returns Ok(true) if the hash
matches, Ok(false) if it doesn’t, or Err on I/O failure.
This validates file integrity without decompressing the audio. Requires version >= 3980.
Sourcepub fn frames(&mut self) -> FrameIterator<'_, R> ⓘ
pub fn frames(&mut self) -> FrameIterator<'_, R> ⓘ
Returns an iterator over decoded frames.
Sourcepub fn file_info(&self) -> &ApeFileInfo
pub fn file_info(&self) -> &ApeFileInfo
Access the parsed file info (header, seek table, derived values).
Sourcepub fn seek_remainder(&self, frame_idx: u32) -> u32
pub fn seek_remainder(&self, frame_idx: u32) -> u32
Get the byte alignment remainder for a given frame. This value is needed when decoding raw frame bytes externally.