Stream from disk
imprompt opened this issue · 10 comments
I would like to implement disk streaming capability to allow loading large instruments. Any guidance here would be very welcome to make this fit better into the existing code.
For SF2 files (to get started):
Loading an instrument:
SF2Reader::readSamples() - limit loading to first blocksize number of samples
Playing an instrument:
Something needs to trigger the reading of the full sample. I suppose this should be in sfzero::Synth::noteOn() where we could submit an asynchronous loading of the full sample into a temporary buffer. Then when sfzero::Voice::renderNextBlock() (where I understand the bulk of the rendering is done) reaches the end of it's pre-cached block, it could look at the temporary full-sample buffer.
Does this sound the best way?
Opened the same issue in altalogix/SFZeroModule - probably the more appropriate place for a juce project?
Stay away from the altalogix fork (they did unspeakable things to the code style). The schellingb and jamiebullock forks are fine.
Your basic idea sounds good. A couple of notes:
-
I'd get started with SFZ files rather than SF2. SFZero is fundamentally an SFZ player, with the SF2 support bolted on later. Also, do SF2 instruments in the wild really get so big that streaming is helpful for them? SFZSample::Load() is where the sample loading happens for SFZ files.
-
There isn't currently an appropriate thread to do the background reading; you'll have to add one. noteOn() would send it a message of some kind to initiate the loading. Once the thread has read it, it would install it in the SFZSound (with appropriate mutex locking).
-
There are two advantages to streaming: quicker plug-in startup, and reduced memory use. For the latter, you'd also have to have a mechanism to eject the buffers after they're no longer needed. That means tracking which buffers are still in use.
Thanks for the reply Steve (and your excellent library!) and the heads-up on the different forks. It seems the schellingb fork is pulling updates from the jamiebullock fork so may be the best place to start. I had planned on implementing SF2 first because I have a 2GB SF2 I want to get working on the iPad and are more familiar with the file format, but I see Polyphone can convert to SFZ so will look at SFZ first. I can use my experience of implementing disk streaming in an old sample player "VSamp" I wrote for the mac in the 90s, but will hopefully avoid doing 'unspeakable things' to your code style.
Okay, so SF2 does have a real-world use case. I have VSamp! I used to use it live ca. 2010.
https://github.com/christophhart/streaming_sampler
Any ideas on how that could be integrated?
I've implemented my own in the SFZero framework, including support for iOS AUv3. It's currently hard-coded to always operate for SFZ files (only - not implemented for SF2) and preload the first 44100 samples of each sample and then stay at least 22050 samples ahead of the audio stream:
https://github.com/imprompt/SFZero/blob/DIsk-Streaming/README.md
All working OK, but I'll tidy it up further including making the preload size a changeable parameter.
Maybe I'm missing something but I can't seem to find the disk streaming changes in the code.
Sorry I hadn't published the module changes. It's there now:
https://github.com/imprompt/SFZeroModule/tree/Disk-Streaming
Thanks.
It works great.
I think I'll fork it for a Linux version.
That's great. I'll tidy up the code further and submit a pull request to Steve's original code, although I used the altalogix branch as a starting point as this had a working OSX AU plugin. I'm undecided yet as to whether I should get the disk streaming going with sf2. I agree with Steve's comment above that SF2 appear's to have been bolted on and it was easier to begin with SFZ.