fluid-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [fluid-dev] Timing revisited


From: Josh Green
Subject: Re: [fluid-dev] Timing revisited
Date: Thu, 23 Apr 2009 11:18:55 -0700

On Mon, 2009-04-20 at 20:59 +0200, David Henningsson wrote:
> The callback I'm talking about is mainly the same thing as the as the
> sample timer, i e the possibility to receive notification before/after
> fluid_synth_one_block, and from the "audio thread" (or more correctly -
> whatever thread who calls fluid_synth_one_block). This has the advantage
> that the call will be synchronized, so there are no race conditions
> between the "audio thread" and some other thread (simply because there
> is no need for another thread at all).
> 
> But I've recently come to think of a disadvantage as well. If we're
> low-latency, it's important that fluid_synth_one_block finishes as soon
> as possible. If we do more things, we risc a buffer underrun if one of
> these calls take unexpectedly long time (e g when the player loads
> another midi file). This brings me into thinking...
> 


Ohh, I get it now.  So the callback in that case would be running
synchronously.  That could indeed be a problem, as you mention.  Any
operating system calls can block for unspecified amounts of time
(malloc, fopen, etc) and should be avoided in the audio synthesis
thread.


> > What about using some sort of
> > message queue to pass the MIDI events to the synth?  
> 
> ...well, something like that.
> 
> > I imagine it is
> > probably good to try and avoid locks if at all possible in the synthesis
> > thread, but perhaps some lock-less mechanism can be used (circular
> > buffer for example) to pass the events.  Does this make sense?  glib has
> > portable atomic integers which could be used for this task.
> 
> I don't know if the overhead of using atomic integers (compared to
> ordinary non-thread-safe integers), perhaps we should have a parameter
> in the synth that sets it in either "thread-safe" or "non-thread-safe"
> mode. In the fast-file-rendering case, there is just one thread and a
> callback to the player is done after every FluidBuffer samples.
> 
> (pasted from another thread, I think it belongs here)
> 

On single 32 bit CPU systems I think generally all 32 bit integers are
atomic, when simply reading/writing them.  Its when you have multiple
CPUs that they may not be atomic.  Memory barrier tricks and other
assembly instructions are used for specific architectures to provide
additional atomic operations (add/sub/test, etc).  These instructions
are generally very fast, compared to the alternative of using mutexes,
especially in the case where contention occurs.

If you have a queue with one consumer and one producer, then you can
simply use an atomic integer to atomically add/subtract how many bytes
are in the buffer and the head and tail of the circular buffer are only
accessed by one or the other thread.

The advantage of this scheme, is that the synthesis thread would never
get blocked by a lower priority thread, which could be the case when
using a mutex and lock contention occurs.

I'm kind of surprised that glib doesn't already have a lockless circular
queue data type, since it has everything else needed to create such a
thing.  Perhaps that would be something to contribute back to glib!

> >> As stated earlier, we disagree on this. I can see the use for having
> >> other timers than the sample timer (especially after having read
> >> about the ALSA sequencer), but if the wall clock implementation has
> >> concurrency problems, it's broken. To fix that, it would be better to
> >> use the sample timer feature in the synth just to get notification at
> >> the right time, but then try to figure out a better value for the
> >> msec parameter.
> > When you refer to the concurrency issues with the FluidSynth sequencer
> > and synth, are you referring to an existing multi-threading issue
> > which could cause
> > a crash or unexpected behavior due to a lack of a mutex or are you
> > referring to the limitation that MIDI events can only be processed
> > every FluidSynth buffer size?
> 
> The former. It seems to me that either fluid_synth_one_block should not
> be called at the same time from one thread at the same time as another
> thread calls fluid_synth_handle_midi_event and friends. So either we
> have concurrency issues, or I'm overlooking a smart and undocumented
> locking mechanism. (synth->busy seems to prevent some things but not all
> of them? And commented out in some places?)
> 
> // David


I wouldn't be surprised if there are threading issues, so what you have
found is likely a valid issue.  I have also suspected such issues could
exist, since there doesn't seem to be much regard for locking sensitive
data or anything of the sort.  This could lead to synthesis issues (if
multiple synthesis parameters are dependent or on multi-CPU systems) or
worse case would be crashes.

        Josh






reply via email to

[Prev in Thread] Current Thread [Next in Thread]