falkTX / Carla

Audio plugin host
https://kx.studio/carla
1.56k stars 144 forks source link

JSFX plugin format #1487

Open jpcima opened 2 years ago

jpcima commented 2 years ago

This is a source-based plugin format, which is made by Cockos and part of Reaper. (Note that JSFX does not stand for JavaScript.)

There are dozens of these plugins shipped in Reaper (see InstallData/Effects folder). Most are rather short source code files, tagged with a free software license on them.

The implementation of JSFX is partially free software. EEL2 is the underlying programming language, which is published as part of WDL. There exists a free software implementation in jsusfx.

Some notes

falkTX commented 2 years ago

lets keep the discussion here then. my main doubt against all this is a sorta "vendor lockin" if we place this in carla. It kinda makes sense for carla to load them since it is really a plugin format in the end, plus the drag&drop would make this handy... but it would be something limited to carla instead of being usable everywhere.

the dynamic nature of these files likely makes it very tricky to have as general plugins though, that part I do not know how to solve.

If carla really ends up supporting jsfx, then I would see it as a motivation to do a carla mini-host, a 1-to-1 wrapper for the things carla is able to load.

how fast is the scanning for these files?

jpcima commented 2 years ago

how fast is the scanning for these files?

This is not yet at a stage where I'm able to tell about the scanning speed.

limited to carla instead of being usable everywhere.

The idea is to go with the jsusfx library after patching it with some desirable updates. It doesn't look much maintained nowadays, so a fork seems in order.

These might be problems

With that being said, in Reaper the use of these as plugins is pretty transparent, same as other plugin types.

jpcima commented 2 years ago

There is the current status at this branch. Currently it builds the support libraries. https://github.com/jpcima/Carla/tree/jsfx

falkTX commented 2 years ago

Looks good so far. How are we going to deal with plugin folder, is there a spec to where these would be stored? If not, we probably need to store filenames as the carla project state.

Also, I asked about the speed of discovery of such plugins because we can either discovery them through python alike ladspa, dssi, vst2 and vst3 or through libcarla_utils.so that handles this directly (for those formats where scanning is known to be fast) Would be nice if the scanning was as fast as LV2 discovery, but not sure if really possible.

jpcima commented 2 years ago

How are we going to deal with plugin folder, is there a spec to where these would be stored?

It's from some knowledge gathered so far, correct if I'm wrong.

There is not a path defined by spec, neither can Reaper set custom folders; instead, all goes in a fixed "Effects" folder. If there exists something like a unique ID, it might be such as analysis/gain_reduction_scope, a path relative to the effects folder, where the file can optionally be suffixed .jsfx. Files .jsfx-inc should be ignored.

Another thing is the import statements: "this filename will be searched within the JS effect directory" So the plugin should be made aware of what root folder it's loaded from, to set the imports right I guess.

Would be nice if the scanning was as fast as LV2 discovery, but not sure if really possible.

A quick look at jsusfx API hinted this to be possible, but will have to be verified.

jpcima commented 2 years ago

The current progress of JSFX

notably missing

There are TODO(jsfx) mentions at relevant places.

jpcima commented 2 years ago

wondering if this is better in a branch until 100% finalized, or already good enough to be placed in the main branch... what are your thoughts on it?

This depends of your own criteria of what makes it acceptable to merge or not. I'd call it beta for the time being, because of a few remaining items.

Misc: most JSFX sources shipped in reaper have more metadata as comments (plugin category and author) example: //tags: lo-fi distortion filter mangler Perhaps we should parse the info comments. It might be that tags: and author: are planned as keywords for a future JSFX, who knows.

jpcima commented 2 years ago

Verified the state of Jsusfx against Reaper, that's how it is:

jpcima commented 2 years ago

It can be confirmed from Reaper saves that the relative path serves as unique ID. As an example, the unique ID would be analysis/loudness_meter for the file /opt/REAPER/InstallData/Effects/analysis/loudness_meter.

Does Carla provide a way to handle this?

falkTX commented 2 years ago

The File class provides some ways to make relative paths.

During plugin load the carla settings struct provides access to the paths to look for in plugins. So this seems doable to adapt to in carla.

jpcima commented 2 years ago

During plugin load the carla settings struct provides access to the paths to look for in plugins.

And can the discovery have access to the search paths too? It starts only with the absolute pathname.

falkTX commented 2 years ago

For carla utils library yes, for discovery via CLI, no. Which makes sense, if we run carla-discovery-native jsfx /path/to/something.jsfx how could that possibly know what would JSFX_PATH be?

If we keep carla-discovery are purely informational (like done with lv2) and the real searching&parsing through the utils/CachedPlugins.cpp code, then this will be doable. The first call to carla_get_cached_plugin_count usually includes the paths to look for, so we can cache and use that.

jpcima commented 2 years ago

Understood. Then should carla-discovery of jsfx get rid of doInit perhaps? I make this run the compilation, but success can't be guaranteed without the import path deduced properly.

falkTX commented 2 years ago

I would say we should avoid the compilation if possible, or is that required to fetch plugin info?

jpcima commented 2 years ago

I would say we should avoid the compilation if possible, or is that required to fetch plugin info?

It's not required at all, just a note for later work: it needs to check the presence of a gfx section, that tells if plugin would have UI or not. There's a deficiency of the jsusfx library, which can only identify this after compiling (it's fixable).

Currently, discovery follows a logic such as: if doInit, compile, otherwise just read header

falkTX commented 2 years ago

Personally I would be ok with not knowing if jsfx have custom UIs or not. At least initially.

The "doInit" makes sense if process checks are enabled during discovery, but that only applies for carla-discovery not the utils lib

jpcima commented 2 years ago
jpcima commented 2 years ago
falkTX commented 2 years ago

There is a class in carla utils for the locate issues, CarlaScopeLocale or something like that. either put it around the entire file loading or specific sections of it.

jpcima commented 2 years ago

Yes, this source code is C though. I'll fix it. Culprit is here https://github.com/falkTX/Carla/blob/555caea8a0e3aa28c1c1d9df081403b3efeadbe9/source/modules/eel2/source/WDL/eel2/nseel-compiler.c#L5869

jpcima commented 2 years ago

Re: carla-specific IO functions The Jsfx output connects to a function which has the fwrite signature (it writes in chunks). Hence it's not possible to connect with carla_stdout, as is?

falkTX commented 2 years ago

if it expects no newline, then no. all the carla_std* functions append a newline at the end

jpcima commented 2 years ago

it's okay to do a light refactor of carla's io functions, to get access to that FILE handle for direct writing?

also carla_stdout and its friends have FILE* as a static-local into a static-inline function, it could be that these static handles end up multiple. (if multiple source units duplicate the function)

jpcima commented 2 years ago
jpcima commented 2 years ago

Regarding author and category metadata

Many files contain comments similar to these ones.

//tags: guitar modulation filter gain
//author: Cockos

These look similar to the desc: tag except for being commented. Most of the stock jsfx have these, yet it's not a standardized syntax afaik. (it might be for a future extension of the language?) For time being, there is absolutely a possibility of parsing these pseudo-tags.

falkTX commented 2 years ago

Makes sense to try to carefully parse them I think, they provide useful info.

btw, how do we differentiate between FX and synths?

jpcima commented 2 years ago

btw, how do we differentiate between FX and synths?

jpcima commented 2 years ago

It does not support sliders written in that form, and the compilation/readHeader fails: slider1:/amp_models:none:Model

The idea is that this slider (menu rather) controls an index of a file into a directory of wav IR files. These wav files reside in the Data/amp_models folder, whereas the effect is located inside Effects/guitar.

The specification has something to say about this, more precisely: it scans wav/txt/ogg/raw files It does not mention that files should be listed in lexicographical order, but in Reaper they are.

There is library support to implement, but also the pesky path search. (since we have to go one above from Effects and into Data, such that Data is a hardcoded element of the path)

jpcima commented 2 years ago

The sliders whose desc begins with character '-' should be hidden parameters. Specification says

You can also hide sliders by prefixing their names with "-". Such parameters will not be visible in the plug-in UI but still be active, automatable, etc.

Edit: perhaps leave that one for now until UI support

jpcima commented 2 years ago

There is this unspecified syntax, which creates a slider with empty range (min=max=0), and its purpose is to serve as output-only parameter. (but we don't normally know that unless examining the code) slider10:0,Reduction (dB)

The observation related to the item above is that DSP can assign to a slider variable and have the slider move as a result. Carla should detect the slider change respond to jsfx sliderchange() API, and automate the parameter. Edit: check also the slider_automate API which jsusfx has marked as to-do

GavinRay97 commented 2 years ago

Just wanted to come and drop a huge note of appreciation and support for this!

Many JSFX are as good or better than paid plugins, and there's such a large community collection of them.

Would be incredible to have a cross-platform implementation of JSFX host.

Thank you for working on this =)

jpcima commented 2 years ago

Would be incredible to have a cross-platform implementation of JSFX host.

There exists one as part the host support library. If you can build this, you get a vst plugin which can host jsfx. https://github.com/jpcima/ysfx

I'll write a document later on how to build this.

GavinRay97 commented 2 years ago

Oh this is awesome, thanks for the tip @jpcima !