Skip to main content

ApeDecoder

Struct ApeDecoder 

Source
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>

Source

pub fn new(reader: R) -> ApeResult<Self>

Open an APE file and parse its header.

Examples found in repository?
examples/decode.rs (line 12)
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
Hide additional examples
examples/decode_to_file.rs (line 23)
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}
Source

pub fn info(&self) -> &ApeInfo

Get file metadata.

Examples found in repository?
examples/decode.rs (line 14)
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
Hide additional examples
examples/decode_to_file.rs (line 26)
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}
Source

pub fn total_frames(&self) -> u32

Total number of frames in the file.

Source

pub fn decode_frame(&mut self, frame_idx: u32) -> ApeResult<Vec<u8>>

Decode a single frame by index, returning raw PCM bytes.

Source

pub fn decode_all(&mut self) -> ApeResult<Vec<u8>>

Decode all frames, returning all PCM bytes.

Examples found in repository?
examples/decode.rs (line 20)
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
Hide additional examples
examples/decode_to_file.rs (line 37)
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}
Source

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.

Source

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().

Source

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.

Source

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.

Source

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.

Source

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?
examples/decode_to_file.rs (line 45)
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}
Source

pub fn wav_terminating_bytes(&self) -> u32

Get the number of terminating data bytes from the original container.

Source

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.

Source

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.

Source

pub fn stored_md5(&self) -> &[u8; 16]

Get the stored MD5 hash from the APE descriptor.

Source

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.

Source

pub fn frames(&mut self) -> FrameIterator<'_, R>

Returns an iterator over decoded frames.

Source

pub fn file_info(&self) -> &ApeFileInfo

Access the parsed file info (header, seek table, derived values).

Source

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.

Source

pub fn read_frame_data(&mut self, frame_idx: u32) -> ApeResult<Vec<u8>>

Read the compressed data for a given frame from the source. The returned bytes include alignment prefix and padding as needed by the APE bitreader. Use seek_remainder() to get the bit offset.

Auto Trait Implementations§

§

impl<R> Freeze for ApeDecoder<R>
where R: Freeze,

§

impl<R> RefUnwindSafe for ApeDecoder<R>
where R: RefUnwindSafe,

§

impl<R> Send for ApeDecoder<R>
where R: Send,

§

impl<R> Sync for ApeDecoder<R>
where R: Sync,

§

impl<R> Unpin for ApeDecoder<R>
where R: Unpin,

§

impl<R> UnsafeUnpin for ApeDecoder<R>
where R: UnsafeUnpin,

§

impl<R> UnwindSafe for ApeDecoder<R>
where R: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.