README.md
SemantiFX JUCE plugin
The plugin exposes a fixed pool of two slots for each catalogue type: EQ,
distortion, compressor, and reverb. The saved chain state property stores an
ordered comma-separated subset of those slots, such as eq-1,reverb-1.
Hosts see every slot's parameters at construction time, including its bypass parameter.
Chain structure is saved state, and solo is a transient UI control rather than a host
parameter.
Build and run on macOS
| 1 | cmake -S plugin -B plugin/build -DCMAKE_BUILD_TYPE=Debug |
| 2 | cmake --build plugin/build --target Semantifx_Standalone -j 4 |
| 3 | open plugin/build/Semantifx_artefacts/Debug/Standalone/Semantifx.app |
Build all formats and run the tests with:
| 1 | cmake --build plugin/build -j 4 |
| 2 | ctest --test-dir plugin/build --output-on-failure |
JUCE is fetched at tag 8.0.8. Release artifacts use a separate build
directory with -DCMAKE_BUILD_TYPE=Release.
Slot parameters and chain editing
Each slot has the generated catalogue parameters and a continuous bypass
parameter. IDs are derived from the generated table, for example
eq1_low_shelf_gain_db, distortion2_drive_db, and reverb1_mix. The host
parameters also include global outputGain, mix, and bypass.
The card rack shows the saved effect chain from left to right. Select a card to
edit it, use its bypass or solo toggle for transient auditioning, and remove or
drag cards to change the chain. Left and right arrows reorder the focused card.
Delete or Backspace removes it. Enter or Space selects it. The trailing +
card lists catalogue types that still have a free slot.
EQ keeps its interactive response graph. Other effect types show one rotary
control per generated parameter, with its catalogue display name and unit.
An empty chain passes audio through and shows Press Shape sound, or + to add an effect.
Shape sound and optimize chain
- Press
Listen 10swhile audio is passing through the plugin. - Enter a target prompt.
Shape soundasks the worker to assemble a chain, applies that chain, and then starts optimization from the current slot values. A no-change assembly clears the chain and stops withPrompt asks for no change; chain cleared.Optimize chainruns parameter optimization on the current non-empty chain.
During a run, Stop keeps the latest audible values and Revert restores the
composition, parameter values, and bypasses captured before the first start.
Escape performs Revert. Every progress snapshot containing parameters is
applied on the message thread, so the current candidate is audible while the
worker runs. A final analysis_result is applied as the current configuration.
Changing the chain structure restarts analysis immediately. Releasing a knob on an active slot schedules one restart after 300 ms, so a group of knob edits becomes one request. Bypass and solo changes do not restart analysis. A restart keeps the original pre-run snapshot, and stale worker results are discarded by request ID.
Import accepts a successful analysis_result JSON for the current chain and
validates its order, instances, effects, names, units, and finite values before
applying it.
Linux full build
On a Linux box with the X11/ALSA/FreeType dev packages installed
(libasound2-dev, libfreetype-dev, libfontconfig1-dev, the libx*-dev
set, libglu1-mesa-dev, mesa-common-dev, libcurl4-openssl-dev,
libjack-jackd2-dev) plus xvfb, the full plugin builds and validates with
one command:
| 1 | scripts/check-plugin-linux |
This configures plugin/build-linux (RelWithDebInfo, reusing the JUCE
checkout at SEMANTIFX_JUCE_DIR or /tmp/juce-8.0.8 when present), builds
every target, runs the whole ctest suite, and validates the VST3 with
pluginval (strictness SEMANTIFX_PLUGINVAL_STRICTNESS, default 10) when the
SEMANTIFX_PLUGINVAL binary exists. The equivalent manual steps are:
| 1 | cmake -S plugin -B plugin/build-linux -DCMAKE_BUILD_TYPE=RelWithDebInfo \ |
| 2 | -DFETCHCONTENT_SOURCE_DIR_JUCE=/tmp/juce-8.0.8 |
| 3 | cmake --build plugin/build-linux -j 24 |
| 4 | ctest --test-dir plugin/build-linux --output-on-failure |
| 5 | xvfb-run -a /tmp/sfx/tools/pluginval/pluginval --strictness-level 10 \ |
| 6 | --validate-in-process --timeout-ms 600000 \ |
| 7 | --output-dir /tmp/sfx/logs/pluginval \ |
| 8 | --validate plugin/build-linux/Semantifx_artefacts/RelWithDebInfo/VST3/Semantifx.vst3 |
Linux: DSP-only checks
Linux does not need the JUCE GUI or audio modules for the reusable catalogue DSP. Run:
| 1 | scripts/check-dsp |
This builds and runs the JUCE-free math, capture, effect parity, and slot-pool
tests. The full plugin and processor tests must be built on macOS, where the
JUCE GUI and audio dependencies are available, or on Linux via
scripts/check-plugin-linux (see "Linux full build" above).
scripts/check-plugin-syntax goes one step further on Linux: it clones the
pinned JUCE tag into plugin/build-juce-src (or uses SEMANTIFX_JUCE_DIR) and
runs a header-only syntax compile of every plugin source and test with warnings
on. It catches type, signature, and include mistakes in the JUCE code without
building JUCE; for linking and runtime behaviour use the macOS build or
scripts/check-plugin-linux.
Offline render tool
plugin/tools/render.cpp builds the semantifx_render target in both the
full and DSP-only configurations. It renders a WAV file through a serial chain
of the exact catalogue DSP the plugin uses, for listening tests and
diagnostics:
| 1 | cmake -S plugin -B plugin/build-dsp -DSEMANTIFX_DSP_ONLY=ON |
| 2 | cmake --build plugin/build-dsp --target semantifx_render -j 4 |
| 3 | plugin/build-dsp/semantifx_render <in.wav> <out.wav> [--block N] \ |
| 4 | [--effect TYPE[:name=value,...]]... |
Effects apply in the order given; parameters not listed stay at their
generated defaults. Accepts mono and stereo input as 16/24-bit PCM or 32-bit
float WAV, writes 32-bit float WAV out at the input sample rate (default block
512), and prints input/output peak and RMS dBFS to stdout. Unknown effect
types, unknown parameter names, and out-of-range values are rejected.
inference/diagnostics/render_gallery.py (via scripts/render-gallery)
renders the full preset gallery with this tool.
The plugin uses JUCE's dsp::Convolution for reverb in real time. Generated
impulse responses are built by the message-thread timer, not by the audio
callback. The direct convolver remains available for parity tests and offline
DSP checks.