[email protected] wrote:
Quoting David Henningsson <[email protected]>:
The fluid_synth is becoming increasingly large and complex. I've
started to think of it as two parts, a state machine, and a voice
renderer. The voice renderer is strict real-time, and corresponds
roughly to fluid_synth_one_block and everything below that.
Just for clarification, are you referring to code organization and/or
code changes?
Both. To increase cohesion, let's say that the fluid_synth object could
own a fluid_voice_renderer object, which only deals with the voices and
not the MIDI.
Are you referring to fluid_synth.c in particular?
More the object than the file, but yes.
As I get back into libInstPatch and Swami development, I'm going to
start seriously considering adding libInstPatch support to FluidSynth.
Ah, and then there is the Swami use case, which has its unique
requirements. Keep forgetting about that...
If this goes well, then we may want to just make it the core of the
instrument management in the future. Making FluidSynth GObject
oriented, isn't much of a step beyond that. With GObject introspection
being a hot topic these days, that could lead to just about any language
binding which supports it, automatically. This would be FluidSynth 2.0
though and would probably change the API significantly.
So yet another U-turn on the glib dependency, dropping thoughts about
iPhone etc?
The state machine is everything else, and a MIDI synthesizer is a state
machine; people expect to set a variable in there and be able read it
correctly afterwards. On the other hand, we can probably ease the
real-time requirements on this part.
The state machine is multi-threaded by default, but we must be able to
switch it off to avoid overhead for some use cases, such as the
embedded ones, and fast-render. The more MIDI events that can be
handled within a fixed time, the better, though. But for the harder
ones (e g program change) we are allowed to use mutexes.
I don't think the multi-thread stuff adds too much overhead. If the
fluid_synth_* functions get called from the synthesis thread, which is
the case for fast render, then no queuing is done, in which case the
only real overhead is checking to see if its the synthesis thread and
assigning the thread ID in fluid_synth_one_block.
In my long-term thoughts, I would like to avoid checking thread ID's as
far as possible. We should instead assume that only one thread calls
fluid_synth_one_block at a time, and that calls to the state machine are
either synchronized or not synchronized depending on the configuration
/ use case.
I think it is the right way to make us resistant to the thread-jumping
problem Ebrahim reported.
This also proposes moving the thread boundaries from before fluid_synth
to between the state machine and the voice renderer. The voice renderer
needs an in-queue of "voice events", events so much prepared that the
voice renderer can meet its real-time requirements.
This would also have the advantage of moving the sfloader callbacks
outside the most realtime sensitive code.
That seems like a good idea. A lot of state machine processing though,
relies on the current state of voices.
Hmm? It could be that swami wants information about the current voices,
but otherwise I would say that information goes from the state machine
to the voice renderer only. What information does it need that comes
from the voices rather than the current MIDI state?
However, nothing new without a downside. Since the sample is used by
the voice renderer, freeing a preset or soundfont is not solved easily.
But outlined, first we should check if there is an audio thread
running, if there isn't (embedded case, fast-render), we can just go
ahead. Otherwise send a voice event saying we should kill active voices
referencing the preset or soundfont. We then block the call until the
audio thread has processed our message (simplest). Optionally we could
return asynchronously, but then we still need some kind of garbage
queue.
I think reference counting would help a lot with this. When a voice is
using a sample, it holds a reference. The sample references its parent
SoundFont, etc. This is how libInstPatch works. If a SoundFont gets
removed or changed, different presets get assigned, causing the samples
to become unreferenced, ultimately freeing the SoundFont if no more
references are held.
We must make sure freeing a SoundFont never happens in the audio thread,
since then it'll lose real-time. So I don't see how this solves the problem.
For the multi-core support to make a difference - assuming
rendering/interpolating voices it what takes the most time - it would
be nice to add a pre-renderer. This pre-renderer would be a function
that copies the current value of a voice, assumes nothing happens to
that voice, and renders a few buffers ahead, say 100-500 ms. It should
run in one or several non-realtime threads, depending on the number of
CPU cores. Now the voice renderer, after having processed its in-queue,
takes these pre-rendered buffers instead of rendering them directly,
assuming nothing happened to the voice and the renderer has the buffer
available.
That sounds like a good idea. There could be some change prediction
logic too, to select those voices deemed less likely to change (haven't
been changed in a while or are known not to change for some time if
playing back a MIDI file).
Jimmy's post got me thinking that perhaps we should cache the result of
the rendering, especially for drum tracks which are often repetitive. At
least it will speed up rendering of techno music ;-)
Nice to hear your thoughts on FluidSynth future. It would be good to
get an idea of the next phase of development. As I mentioned, I'll
primarily be focusing on libInstPatch and Swami for the coming months.
So the next release should probably be more focused on bug fixes,
optimization, voice stealing improvements, etc. But limit the amount of
new functionality or code overhaul.
I guess that's more reality based, since we (well, mostly you) just made
a lot of code overhaul, and I won't have time to do this change
currently anyway. It's just that given the recent posts, I just can't
help thinking that perhaps we didn't do the thread safety in the best
way possible.
// David
_______________________________________________
fluid-dev mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/fluid-dev