ADLplug icon indicating copy to clipboard operation
ADLplug copied to clipboard

Many xruns when running as lv2 in Ardour

Open farvardin opened this issue 5 years ago • 23 comments

hello,

when I run ADLplug as standalone, it works fine. However, when I run it from inside Ardour 5.12, there are many Xruns and some audio glitches.

My latency is quite low (2.8 ms), with a higher latency (like 5.8 ms), there are fewer xruns. However, with Dexed, Zynaddsubfx or Helm in Ardour, which are apparently more ressource hungry than ADLplug, I don't have those xruns with the same low latency.

The DSP load is around 40 % with ADLplug (even without playing), while with Helm for example it's around 25%. I'm using the DOSBOX core, with 1 or 2% CPU, so it's not ressource hungry.

Distribution: Linux Mint 19 (latest), with 4.15.0-20-lowlatency kernel, ADL plug 1 beta 2

  • EDIT: relevant Ardour issue at http://tracker.ardour.org/view.php?id=7707

farvardin avatar Dec 03 '18 07:12 farvardin

Hello @farvardin

Distribution: Linux Mint 19 (latest), with 4.15.0-20-lowlatency kernel, ADL plug 1 beta 2

Beta 2 is an old version and contains a plethora of issues. Can you try the latest version available in the releases ? this has a Debian package available, which I hope to be generic enough to run on most Linux OS.

If this doesn't help, are you able to try whether this happens also in -rt kernel configuration ?

My latency is quite low (2.8 ms), with a higher latency (like 5.8 ms), there are fewer xruns. However, with Dexed, Zynaddsubfx or Helm in Ardour, which are apparently more ressource hungry than ADLplug, I don't have those xruns with the same low latency.

I designed the plugin for best prevention of x-runs possible, but there are a few suspects to look at. In particular this synth involves a background task which dynamically reoptimizes allocations of chip channels, not present in a FM synthesizer like Dexed.

Does your workflow involve a lot of parameter manipulation ? has it happened also while idle ?

jpcima avatar Dec 03 '18 09:12 jpcima

Problem is identified. It seems because the background worker inherits a realtime priority when it shouldn't. Gotta fix

jpcima avatar Dec 03 '18 12:12 jpcima

@farvardin turns out this is an issue at Juce side and I attempted a fix. I have not officialized it yet in my source fork but I allowed binaries to build with an experimental patch.

Do you mind testing binaries and report whether this solved the issue? at my side no xruns at 2.67ms latency. https://github.com/jpcima/ADLplug/releases/download/latest/adlplug_amd64.deb https://github.com/jpcima/ADLplug/releases/download/latest/opnplug_amd64.deb

jpcima avatar Dec 03 '18 16:12 jpcima

Thanks a lot for your efforts. I haven't done some parameter manipulations, I just load ADLplug and use the default instrument. When idle, there is no xruns, but when a play a note, it happens, for example 3 Xruns in 5 seconds, playing a single note.

The lowlatency kernel seems to be a replacement for the -rt kernel. https://wiki.ubuntu.com/RealTime

I've tried your beta 4 binary, but I'm afraid, it's the same like before :( (it looks like the binaries were built before your patch) In standalone, it's ok, like before, it's only with Ardour that there are those xruns...

farvardin avatar Dec 03 '18 23:12 farvardin

it happens, for example 3 Xruns in 5 seconds, playing a single note.

It's a similar symptom as I've been able to experience on my own side, which has been resolved after patching Juce.

(it looks like the binaries were built before your patch)

Can you guarantee me that you have picked latest from releases ? as I linked in my previous message. not beta4 or nightly. (And made sure that you don't have a conflicting installation on the system from a source code build.) From the info dialog, the dev version is going to advertise itself as beta4, but that is expected.

If the problem is present, can you experiment this:

  • run standalone, and capture the output ps ax -L -o 'policy,sched,pri,rtprio,args' | grep -i adlplug while it runs
  • run LV2 in Jalv as jalv.gtk https://github.com/jpcima/ADLplug and capture the same ps command as before
  • post both results

jpcima avatar Dec 03 '18 23:12 jpcima

I've clicked on the links, but on the release page I can see:

Latest Pre-release latest be54e95

@jpcima jpcima released this 24 days ago

I'll test the commands tomorrow!

I don't have any source build, I had a previous binary installation from kxstudio, which I've uninstalled

farvardin avatar Dec 04 '18 06:12 farvardin

Revision build be54e95 will be fine. Disregard about the information saying "24 days ago"; that was awkardness of setting up the continuous release onto github but it's very recent in reality. Usually the new build is available within 20 minutes after I make an edit.

jpcima avatar Dec 04 '18 09:12 jpcima

Here are the results:

ps ax -L -o 'policy,sched,pri,rtprio,args' | grep -i adlplug TS 0 19 - ADLplug TS 0 19 - ADLplug TS 0 19 - ADLplug TS 0 19 - ADLplug FF 1 45 5 ADLplug TS 0 19 - ADLplug TS 0 19 - grep -i adlplug

and

ps ax -L -o 'policy,sched,pri,rtprio,args' | grep -i adlplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug FF 1 45 5 jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - jalv.gtk https://github.com/jpcima/ADLplug TS 0 19 - grep -i adlplug

No problem for running adlplug as standalone or as a plugin in jalv. They sound both the same, and no Xrun at all.

It's only with ARDOUR that I got bad experience. I'm sure the plugin doesn't result from a previous install, because when I uninstall your latest binary, the plugin won't show up in Ardour, it's reported as missing (and when it's present it advertise as beta 4, and the default install from kx studio is beta 2). I can't run the previous ps command when adlplug is launched from ardour though, it must be contained somehow else.

farvardin avatar Dec 08 '18 18:12 farvardin

I can add something else, I've tried to record the adlplug in Ardour directly into an audio track (also in Ardour). Then I get a massive amount of Xruns (something like 1800 xruns in 30 seconds). There is not such a problem if I record with an other instrument (dexed for example).

farvardin avatar Dec 08 '18 20:12 farvardin

I have identified the issue : it's a problem of Ardour. When this software instantiates a plugin which has lots of input control ports, it creates a big CPU overhead, inside Ardoud itself. After some intense debugging session, I was able to figure out that a very simple plugin with tons of parameters is going to overload Ardour CPU load.

Therefore, it's not a thing that I can solve on my side, it's a problem to report to Ardour developers.

ADLplug is a plugin which has next to 970 parameters. (because of 16-part duplication)

jpcima avatar Dec 14 '18 18:12 jpcima

I've also tried the lv2 plugin inside LMMS (using Carla Baypatch). It's much better than in Ardour 5, but in some occasion, I still get some xruns. I don't use many other DAW on linux, so I can't tell for the other. I'll definitely write a bug report to Ardour about this: I can understand now why DrumSynth, with more than 2500 parameters, is unusable in Ardour. But maybe it's a technical constrain which can't be fixed.

For improving how ADLplug works as LV2 (and maybe VST too), we can wonder if we need all those 970 parameters in ADLplug: because of the 16-parts, if I understand well, there is one part for each midi channel (in LMMS channel 1 was driving part 1, channel 2 part 2 etc). (In ADLmidi beta 2, it was just called Midi Channel)

But do we need multiple channels in the LV2, for using as single instrument in DAW? I didn't find how to play several parts together, like in Zynaddsubfx (I don't know if it's possible). So I suppose the 16 parts are from the original code for playing midi files, with 16 different channels.

As a quick and dirty workaround, I've just stripped down the 15 extra parts in resources/lv2/ADLplug.lv2/ADLplug.ttl, keeping only the first part, and compiled it as LV2. Now it works perfectly well in Ardour (only 64 parameters instead of 970).

What do you think? Is it possible to create an option for having only the first part in some occasion, and more in others (but for what use?), or only 16 parts when using as stand-alone... I suppose as standalone you can input several midi instruments, each one using its own channel.

farvardin avatar Dec 15 '18 13:12 farvardin

if I understand well, there is one part for each midi channel

Part and channel are interchangeable terms. The choice of word is based on terminology of Roland GS; in fact I modeled the multi-instrument feature after a GS synth plugin.

we can wonder if we need all those 970 parameters in ADLplug

This is true in many cases, but there was a rationale behind doing this.

  • The GM synthesizer takes advantage of standardized instrument banks, of which there exists a large available quantity.

  • Second, an emulation is efficient on the processor when you pack many instrument channels on single chips. That's especially true of accurate Nuked emulators which operate nearly identical to the electronic circuit. In such a case, the difference of efficiency between a single and multiple instances is very significant. (if you tried Nuked OPN2, you will surely have noticed how it's a problem :smiley:) A thing is: ADLMIDI has a great ability to optimize the chip usage, a good thing to couple with Nuked emulator, and it's a shame to skip this functionality.

I didn't find how to play several parts together, like in Zynaddsubfx (I don't know if it's possible).

It works out of the box, you can try by sequencing a MIDI file into it. You should make sure the host is not blocking the program change messages. (since you mention Carla, I remember there was a setting necessary to change in this particular host. Jalv was fine)

As a quick and dirty workaround, I've just stripped down the 15 extra parts

It's probably a workable short term workaround. For long term, I'd rather if Ardour devs optimized this case. Link me the bug report if you make it.

On occasion I'll have a look at this Ardour problem myself. It's better this from my point of view, than to introduce such complication into the project.

jpcima avatar Dec 15 '18 14:12 jpcima

ADLplug is a plugin which has next to 970 parameters. (because of 16-part duplication)

This makes me wish that LV2 would have deprecated control ports (as was originally intended). if you have > 900 controls, prefer LV2 Properties, and Patch Set/Get. That scales to millions.

Keep in mind that host-exposed control-ports should also be a reasonable number in general. Ideally something that can be mapped to a control-surface for automation (around 8..16). No user is going to dial through 970 controls to find the correct one to automate or MIDI map it.

x42 avatar Dec 15 '18 17:12 x42

@x42

This makes me wish that LV2 would have deprecated control ports (as was originally intended). if you have > 900 controls, prefer LV2 Properties, and Patch Set/Get. That scales to millions.

Well thanks for the hint about using patch extensions. That would be certainly fine with me if not for some problems.

  1. I don't find at all an example how to use it, and 2. I have lot of doubt on widespread support from LV2 hosts. (grep searching into jalv+lilv sources did not yield me results)

About Ardour

I have tried Ardour 5.12 versus Ardour 6 git. It has been an very significant performance difference between both CPU loads. On Ardour 6 the processor overhead is very largely reduced, and at low latency the plugin was usable. (judging by DSP% on my machine, an approximate factor of 5-6x). If only the dynamic_cast removal was the only optimization threough versions, it's a massive impact optimization as I'm concerned, and may be worth a backport into version 5.

No user is going to dial through 970 controls to find the correct one to automate or MIDI map it.

I'd like to facilitate this by some kind of grouping. Would LV2's port groups do? LV2's appeared to be designed for a different purpose as documentation states : "Multi-channel groups of LV2 ports".

jpcima avatar Dec 17 '18 16:12 jpcima

(grep searching into jalv+lilv sources did not yield me results)

grep for patch_Set or get_atom_double for example. jalv supports float, bool, double, integer and file[path] properties since late 2015 https://github.com/drobilla/jalv/commit/add42b10290e261a . Meanwhile Qtractor and Ardour support it as well.

Would LV2's port groups do?

I don't think so. As far as I can tell, http://lv2plug.in/ns/ext/port-groups/port-groups.html are for audio-channel layouts.

However http://lv2plug.in/ns/ext/port-props/port-props.html#displayPriority or http://lv2plug.in/ns/ext/port-props/port-props.html#notOnGUI may help

I don't find at all an example how to use it,

The most widespread use currently is for host-provided file-browser(s). There are a couple of plugins around e.g.https://github.com/x42/convoLV2 . As for float parameters, have a look at some of the https://github.com/OpenMusicKontrollers plugins e.g.

https://github.com/OpenMusicKontrollers/moony.lv2/blob/master/plugin/moony.ttl#L66 https://github.com/OpenMusicKontrollers/moony.lv2/blob/master/plugin/moony.ttl#L161

x42 avatar Dec 24 '18 02:12 x42

For future reference: a simple example to use Parameter/Properties: https://github.com/x42/property_example.lv2

On 2nd thought, that would only solve part of the problem. Ardour will still expose all the properties as automatable controls (still slow in 5.12 [1]). They're all passed via a single control-port. So Ardour won't need to iterate over all ports on every run().

[1] a workaround here would be to mark port or parameter as http://lv2plug.in/ns/ext/port-props/port-props.html#notAutomatic or http://lv2plug.in/ns/ext/port-props/port-props.html#causesArtifacts

x42 avatar Dec 24 '18 04:12 x42

Thanks for the example @x42, it is helpful. For short term I'll use the notAutomatic workaround, then I'll do it proper using the patch extensions. Extending the metadata requires me to make Juce-side implementation for lv2_ttl_generator; judging from current knowledge, it should not be extremely difficult.

jpcima avatar Dec 24 '18 07:12 jpcima

@farvardin update: pleasy try the latest version which has a performance improvement.

What has been done: disable most parameters; I kept the general ones, and also volumes of fm operators: the latter can be useful to automate, they have not too bad resolution, and can drive a modulator to produce dynamic variation of timbre.

The presets will not make sense now so I'll disable them; use states. I don't implement the patch extension for the moment.

jpcima avatar Dec 24 '18 15:12 jpcima

Great, it works flawlessly now in Ardour, with the latest version, thank you very much!

I suppose you prefer to keep all the 16 voices for a restricted set of parameters. I'd prefer to have only one voice with more parameters (such as ADSR), but on the other hand, I'm not sure I'll use the automation in my tracks, and I have no clue what other users would prefer, so it's probably reasonable to do like you did :)

For the preset, I noticed in Ardour there was a preset arrow for ADLplug (in the favorites) but it was empty when we expanded it. It's probably better to disable it then.

Merci encore !

farvardin avatar Dec 27 '18 20:12 farvardin

Great, it works flawlessly now in Ardour, with the latest version, thank you very much!

Thanks for confirming, I will publish the beta release 5.

I suppose you prefer to keep all the 16 voices for a restricted set of parameters.

It's not necessarily that useful. First thing, the chip parameters provide some very limited resolution, due to the small width of OPL registers. For example each ADSR value was coded on 4 bits (range 0-15). You may look at this piece of code, fifth field indicate each parameter length in bits.

Second, there already is a decent amount of control implemented in MIDI, where it translates to chip commands. This is a MIDI Implementation Chart.

For extended control ability, it can be a possibility to offer this over MIDI or OSC. For now, it's not supported to edit instruments over MIDI protocol. I would probably implement this over system-exclusive messages.

jpcima avatar Dec 27 '18 21:12 jpcima

I'm designing some sounds with ADLplug, and now I see a good reason to have more parameters with the generic interface: sometimes it's difficult to get the correct setting from the specific interface, which has no value (or no pop-up value) for control, especially for frequency multiplicator for instance. With the generic interface we get all the values.

farvardin avatar Dec 28 '18 10:12 farvardin

@farvardin then it's a user interface issue? if, so please discuss this topic in a new issue if you don't mind. I will keep this open until adding the LV2 parameter support.

jpcima avatar Dec 28 '18 12:12 jpcima

good idea, I've just opened https://github.com/jpcima/ADLplug/issues/45

farvardin avatar Dec 28 '18 23:12 farvardin