Using AudioFormatWriter/Reader to encode/decode streaming audio across a network

I began to post about how I am struggling to use the AudioFormat classes to get streaming audio working over a network. This is a case where there are only “chunks” of audio available at a time and the writer/reader never has access to the full set of samples. Then I ran across this quote from Jules:

None of the audio format classes are designed for use on open-ended streams (because obviously things like wav, aiff couldn’t possibly do that). So you’d probably need to roll your own solution for this.
Compressing/Decompressing an Audio Stream - #14 by dave96

I happen to have my own solution directly using the FLAC api (and opus)…but was trying to port that into the JUCE bubble so I don’t have to deal with those libraries. Looks like that is not possible, so I’m modifying this post to just be a friendly request to update the AudioFormat classes to allow open ended streams for the formats that allow it. I’m surprised that JUCE has so much audio functionality, and a fairly complete set of networking functionality, as well as audio codec functionality…but you can’t stream encoded audio across a network, which is a fairly common use case.

2 Likes

Well, yes, streaming audio is a totally different problem to reading/writing local audio files, it’s not at all what the AudioFormatReader classes were designed to do.

To do streaming properly, you need a whole layer of tools for discovery, connection, failure handling, bandwidth issues, multiplexing, re-syncing, etc etc. It’s a really complex task and not something we could easily provide a simple class to magically do for you!

The underlying format libraries don’t think of it as a totally separate problem. They solve it with the same library and interfaces. At least FLAC and opus do. Comparing my implementation of streaming with FLAC to your AudioFormat implementation, there are just a few differences (FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE, FLAC::Decoder::Stream::process_single are used in open ended streaming…glossing over details). I don’t want to belabor the request because I can use my own implementation. But, I would hate for someone new to come along and have to deal with those underlying API’s when the functionality could be added to JUCE without too much effort (and you guys are clearly experts at making great APIs). As always, you may look at the details and determine otherwise, but might be worth a look.

That would give someone the ability to have open ended streams that take a memory block of samples and turn it into a memory block of encoded bytes, and vice versa. What the user then does with those memory blocks is up to them. So they bear the burden of sending that data across a network and coordinating both endpoints if that is what they want to do. But at least it would be possible.

You describe a solution that does all of that for them…and yes, that will be a big effort. I think maybe you would be uncomfortable providing the above functionality because the user could mismatch the endpoints by not having the reader/writer correctly configured, and so they would have a bad experience. I can see that point of view as well.