Skip to content

Commit

Permalink
Implement audio/realtime thread for vst-bridge host.
Browse files Browse the repository at this point in the history
The problem with realtime processing in vst-bridge is that although
the host calls process on the plugin from a realtime thread, the
thread which is in the VST host process is not realtime, and hence the
audio thread is stuck waiting for a non-realtime thread. Solving this
comes with some challenges, because we only have one pipe to
communicate through, and this is difficult to synchronize between
multiple threads.

The solution in this patch splits the whole host communication part in
two, by separating out the relevant components into their own struct,
and then providing two instances of the communication pipe instead of
one: One for the realtime thread, and one for the normal thread. Then
we use the process calls as a guide to figure out which thread is the
realtime thread on the plugin side, and any call made using this
thread is forwarded to the VST host process through the realtime pipe
instead of the normal pipe.

We also need to actually set up a realtime thread on the host side,
and this is done by providing a new opcode for setting the thread
scheduler and priority. We just use the same values as the calling
thread uses.

It may be difficult to achieve true realtime performance in wine, for
a variety of reasons, but this patch goes a surprisingly long way, and
I've been able to have hour long sessions with no xruns at all,
whereas before they would occur several times per minute.

A couple of things to look out for if performance is still poor after
applying this patch:

1. Hosts that create their own threads. This plugin is not able to
   apply the realtime scheduler on threads it doesn't own, which means
   the host will still be stuck waiting for non-realtime threads. At
   the time of writing, Wine does not honor Windows thread priorities
   (I've checked the source code), so even if the VST plugin tries to
   do the right thing and increase the thread priority, it will fail
   to do so. I may try to submit a patch to the Wine project at some
   point, if I get the time. However, in many hosts, thread creation
   is configurable under "Number of cores" or some similar setting,
   and turning it off may give better performance. At least it did for
   me.

2. `/tmp/.wine-<UID>` should be a on tmpfs. While wine is
   communicating with wineserver, it uses some temporary files here,
   and these should be on tmpfs, IOW a RAM disk, to make sure the
   thread doesn't stall on I/O.
  • Loading branch information
kramlie committed Feb 11, 2019
1 parent d515cc1 commit cb27d36
Show file tree
Hide file tree
Showing 3 changed files with 401 additions and 250 deletions.
8 changes: 8 additions & 0 deletions common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum vst_bridge_cmd {
VST_BRIDGE_CMD_SET_PARAMETER,
VST_BRIDGE_CMD_GET_PARAMETER,
VST_BRIDGE_CMD_SHOW_WINDOW,
VST_BRIDGE_CMD_SET_SCHEDPARAM,
};

struct vst_bridge_effect_request {
Expand Down Expand Up @@ -93,6 +94,11 @@ struct vst_bridge_midi_events {
struct vst_bridge_midi_event events[0];
} __attribute__((packed));

struct vst_bridge_schedparam {
int policy;
int priority;
} __attribute__((packed));

struct vst_bridge_request {
uint32_t tag;
uint32_t cmd;
Expand All @@ -104,6 +110,7 @@ struct vst_bridge_request {
struct vst_bridge_frames_double framesd;
struct vst_bridge_effect_parameter param;
struct vst_bridge_plugin_data plugin_data;
struct vst_bridge_schedparam schedparam;
};
} __attribute__((packed));

Expand All @@ -114,6 +121,7 @@ struct vst_bridge_request {
#define VST_BRIDGE_PARAM_LEN (8 + sizeof (struct vst_bridge_effect_parameter))
#define VST_BRIDGE_FRAMES_LEN(X) ((X) * sizeof (float) + 8 + sizeof (struct vst_bridge_frames))
#define VST_BRIDGE_FRAMES_DOUBLE_LEN(X) ((X) * sizeof (double) + 8 + sizeof (struct vst_bridge_frames_double))
#define VST_BRIDGE_SCHEDPARAM_LEN (8 + sizeof(struct vst_bridge_schedparam))

static const char * const vst_bridge_effect_opcode_name[] = {
"effOpen",
Expand Down
Loading

0 comments on commit cb27d36

Please sign in to comment.