Hi all,

I would like to propose (and then implement) a new feature to Fluidsynth;
lazy-loading of Soundfont data.

Let me first explain the problem I want to solve:
I'm building a musical instrument (including the hardware) that uses
Fluidsynth for sound output. The player has up to 10 channels available
onto which he can load different sounds/presets from any of the Soundfonts
that are stored on the instrument. Now suppose the player has a few large
Soundfonts and wants to use them all at the same time, but only one or two
presets from each one. Currently this means that every Soundfont has to be
completely parsed and loaded into RAM, even though the player only uses a
fraction of that data for playback. And although the instrument has 1 GB of
RAM, it's still very easy to exceed that limit with a few larger
Soundfonts. To make matters worse, all of this data has to be loaded from
the built-in SD-Card... which takes quite a while.

So my idea was to add an optional feature that enables selective or lazy
loading of preset and sample data from the chosen Soundfonts. When this
feature is enabled and a Soundfont is loaded, the file is not parsed
completely, but only so much that we can extract the high-level preset
information: preset name, bank and program number.  Only when a preset is
actually selected for a channel is the file opened and parsed again. This
time, only the information that is relevant for this particular preset is
read and parsed, including all the samples that the preset uses. And when
that preset is unselected again and not used anymore on any channel, the
related structures and RAM will be freed again.

I had a good look through the Soundfont loading code and think this feature
could be added in such a way that it won't impact the "normal" use. So if
the feature is disabled (which will be the default), Fluidsynths behaviour
and performance will be unchanged. I also think it won't add a lot of new
complexity to the codebase, but that will have to be seen once the
implementation is done.


The feature would bring two major drawbacks (when enabled):

1. The Soundfont structure will not be completely checked for structural
errors at loading time. Doing so would defeat the purpose of this feature,
as we would have to parse the entire file. Most checks will be done
eventually, as presets are selected for playback. But errors in those parts
will surface at a later stage, not during initial load of the Soundfont.
And some checks, like testing if all zone indices of all instruments are
monotonic, won't be possible at all.

For my use case, this isn't really a problem. And after all... there is
always the possibility to disable the feature if you want to validate a
Soundfont completely.

2.  Selecting a preset will definitely incur memory allocation and disk
access. That means that a program change event will most likely take much
more time than it does now. The work will be done in a separate thread so
that parsing the file will not lead to audio buffer underruns. But it would
mean that program change events will be delayed and take effect only after
loading has finished.

Again, for my use case, this isn't a problem at all. I'm not dealing with
automatic program changes, a player has to explicitly change the channel
setup to choose a different one. And currently players of my instrument
have to wait many seconds when he switched to a new setup that uses a few
previously unloaded Soundfonts. With the lazy loading, this time will
actually reduce drastically.


And just make this clear:  this feature is *not* intended to be used with
MIDI file playback. It's mainly useful for situations where a player
chooses a fairly static channel/preset setup and uses Fluidsynth for a
real-time musical performance.

I would really like to get your thoughts on this. Do you think it's a
feature that other Fluidsynth users could benefit from? Do you see any
major obstacles or drawbacks that I've missed?


In preparation for this feature, I've started a larger refactor of the
Soundfont loading code: Breaking it up into more manageable chunks,
cleaning it up and fixing smaller bugs I've found. I hope those changes are
useful even if this new feature doesn't make it into Fluidsynth.
https://github.com/FluidSynth/fluidsynth/pull/360

All the best, and sorry for the long post...

   Marcus
_______________________________________________
fluid-dev mailing list
fluid-dev@nongnu.org
https://lists.nongnu.org/mailman/listinfo/fluid-dev

Reply via email to