Mark McCurry wrote:
> >Currently, Zyn flaunts that requirement big time, which is _the_ reason it
> >crackles and farts on jack io.
> Yes, JACK does not like to wait and ZynAddSubFX breaks this contract big
> In order to resolve this, I would say that one would need to make jobs
> for the backend, such that they can be executed outside of the main
> master::AudioOut loop and master->mutex needs to be severely deprecated.
> If I recall, you did some work to create a ring buffer for input events
> in a separate thread to avoid some of the current issues.
No on the audio, yes on the midi. If you eliminate the grotesque
GetAudioOutSamples() hackery in Master, jack audio actually works very well
driving directly to Master's AudioOut(). In yoshi, there's a subtle safeguard.
The process callback only makes three attempts to acquire the mutex lock. If
it gets the lock, all is well and life proceeds as it should. If it fails to
get the lock, then what gets fed to jack audio is the same samples left in the
buffer from the last cycle. The theory here was that repeating a buffer of
samples occasionally might be a softer error than injecting a buffer full of
silence, and certainly less disruptive than overstaying in the callback. In
practise this seems to work well enough. With the current setup, I haven't seen
it miss the lock yet. I suspect it does happen, but I haven't noticed it either
audibly or in logging. With earlier versions I was seeing a couple every few
minutes or so. The occurrence rate now would be N per hour, certainly not N
Midi is different, kinda slow. Your control work sounds promising in this area.
A simple ringbuffer setup works well. As far as I can tell, the only messages
Zyn cares about are four bytes or less, so it's light, fast enough, and jack's
ringbuffer is well proven, solid technology.
> Some of the work in experimental is going in this direction.
> The controls are being made to be atomic, so you don't need to use
> master->mutex to work with them and there is a job system that has
> received some development that could be used to move stuff out of the
> master::AudioOut loop.
Record and note dumping for example.
> The job system is currently executed in the main loop, but due to the
> implementation it should not be too difficult to move that outside of
> the primary thread.
[ ... ]
> Which optimizations are you refering to?
> I know in one of the previous times I checked your version, there was
> some new code for denormals, but I am not sure if that is what you are
> referencing. (from what I have read, denormals can use significant cpu
> amounts on some processors)
Zyn does what it does by looping through the buffer performing N floating
point operations on every sample, so loop unrolling isn't going to have
much effect. There's a whole lot of places where the buffer is cleared by
a loop doing = 0.0 assignments. A simple memset() does the same thing a
whole lot quicker and lighter. There's enough of them in there to make a
significant difference with more complex patches. There's a very small
number of places where memcpy() can be applied too.
Denormals are strangely interesting, and alarmingly destructive. Yoshi
currently contains the remnants of a few of my experiments, but I'm
starting to think the only one in there now that counts for much is