ruuda / claxon

A FLAC decoder in Rust
Apache License 2.0
287 stars 28 forks source link

Reading undecoded FLAC frames #31

Open antifuchs opened 2 years ago

antifuchs commented 2 years ago

I'm working on a thing that splits FLAC files with embedded CUE sheets into separate tracks, and would love to use this crate to do that: It's got most of the building blocks (a nice StreamInfo representation, good metadata support, a fine data model!), but it doesn't look like I can make use of the library getting decoded samples back.

Would this kind of usage mode be a useful contribution?

ruuda commented 2 years ago

Can you elaborate on what you mean by “getting decoded samples back”? You can alseady use FrameReader to get the decoded samples.

antifuchs commented 2 years ago

Err, yeah, sorry, I should have phrased that better. My goal is to read just plain FLAC frames as data-as-stored-on-disk (without decoding/decompressing into samples). I guess I should have written "undecoded", there.

Anyway, it looks like symphonia's FlacReader::next_packet does something like this already - they are more generic than I need, but the split between "reader that returns undecoded data" and "decoder that turns this data into usable audio" looks like a great mix for my use case (and a decent design overall, it seem!)

ruuda commented 2 years ago

My goal is to read just plain FLAC frames as data-as-stored-on-disk (without decoding/decompressing into samples).

Ah, I see. I think that would be useful, but it would also be difficult to fit into Claxon’s current design.

the split between "reader that returns undecoded data" and "decoder that turns this data into usable audio" looks like a great mix for my use case (and a decent design overall, it seem!)

I am a bit unsatisfied with the way Claxon handles metadata at the moment, and I think this is a similar issue. There is a tension between providing an easy-to-use high-level interface, enabling streaming (avoiding heap allocations), and avoiding parsing (or even reading) of data that you are not interested in. (E.g. if you don’t plan to access the Vorbis comments, we can jump over the entire metadata block without parsing it, and even seek on the underlying reader if supported.) Hound has a similar issue where there are lots of low-level details that some use cases need to access, but it is difficult to unite that with a simple way to just get or write the audio data.

My thinking right now is that the best way to handle this tension is to provide two levels: low-level “building blocks” that can parse or decode (or also write, in the case of Hound) individual pieces, but which may require some boilerplate and understanding of the format to use correctly, and then on top of that a more convenient API that is maybe not the most efficient but that will do the job with little code in 80% of the cases.

Splitting the decoding of the audio data from the frame headers sounds like it would fit that model well too.