eshaz/wasm-audio-decoders

Report amount of consumed bytes as well as decoded samples

miunau opened this issue · 9 comments

miunau commented

Hi,
I have a use case where I'm doing binned analysis on the decoded audio in a streaming fashion where I have to call reset() often due to memory limitations. Basically, I read a stream and decode until I have n samples, then analyse and throw away the PCM buffer. Because of this, besides samplesDecoded, it would be handy to also know how many bytes were consumed while decoding to make it easier to re-feed bytes that didn't complete a frame on the next stream pump. Would this be possible?

eshaz commented

For streaming data, you should use the decode method to send in chunks. As long as you keep the chunk size reasonable while calling decode, it should run indefinitely without memory issues. The decoder will handle any frame boundaries for you when using decode.

I can add a NodeJS stream example to the docs if that's what you're implementing.

miunau commented

Yes, I'm using decode but that cannot guarantee chunks that are fed to it to be the exact frame size as they're fed in from the stream- for example if I feed in a chunk that contains half of a frame at the end, I'd like to know the byte boundary for that for the next decode round after flushing the buffer. As the decoder loses the half-finished frame in memory cuz of the flushing, I'd need the count of bytes consumed to produce the decoded samples to lop off that many bytes from the beginning of the chunk I fed to decode. That way I can keep those n bytes at the end for the half of a frame and concat them together with the next chunk.

If you have other ideas of approaching this I'm all ears :)

eshaz commented

That should be OK for feeding data into the decoder. You can just feed everything you have each time your stream runs through a cycle into the decoder and not worry about the frame boundaries. The decode method is intended to be used this way with streams.

miunau commented

Hmm, but not when I have to reset() to free memory in the middle of the stream, right? If there is an unfinished frame, it would be lost. Or am I wrong in thinking that the decoder keeps the entire decoded buffer in memory until you call reset()?

eshaz commented

You shouldn't call reset() unless you want to decode a different stream. There must be some other problem in your code if you're running out of memory, unless you think there is a bug in the decoder.

Is there some part of your stream that accumulates the decoded PCM? If you're running some analysis on the audio, you'd want to make sure to dereference any audio buffers after the analysis is done so they can be garbage collected.

Generally when streaming, you want to have small chunks flow through, and make sure the only thing being accumulated is the final result.

miunau commented

So the decoder is only keeping the bytes it has not yet decoded in full, not the entire buffer I've fed to it so far? I profiled it some earlier but it might have been my code that was accumulating..

eshaz commented

Yep, it should only keep the last chunk if there is still data to be decoded. I use subarray to read the data, so that full chunk will still be in memory, even though only the end of it is still needed. This isn't a problem in normal use though since chunk sizes are usually less that 100KiB.

miunau commented

Yeah this one was my bad, sorry!

eshaz commented

No problem, glad you fixed it!