DRIFT shreds incoming audio into a cloud of 1,024 grains, then suspends them in a tunable field of pitch, time and space. The result sits somewhere between reverb, delay and synthesis — perfect for ambient pads, dimensional vocals, or pulling a kick drum into a 14‑second tail without losing its punch. Modulation runs internally so motion is built in, not bolted on.
A sample / reference JUCE 8 audio plugin for Corino. Like
corino-halo, DRIFT is a polished,
decorative demo — the knobs are real, automatable parameters but do not process
audio. Its job is to showcase Moonbase licensing in a real VST3 / AU / Standalone
plugin.
Where HALO integrates the older juce::OnlineUnlockStatus bridge, DRIFT uses the
newer moonbase_licensing
JUCE module: native Moonbase API integration (no OnlineUnlockStatus), a
brandable built‑in activation UI, and zero third‑party dependencies (JUCE
WebInputStream transport, vendored nlohmann/json, OS‑native RS256 crypto).
The build produces standard plugin bundles plus a standalone app — no installer:
| Format | Output |
|---|---|
| VST3 | build/DRIFT_artefacts/<config>/VST3/DRIFT.vst3 (macOS / Windows / Linux) |
| Audio Unit | build/DRIFT_artefacts/<config>/AU/DRIFT.component (macOS only) |
| Standalone | build/DRIFT_artefacts/<config>/Standalone/DRIFT.{app,exe} (macOS / Windows / Linux) |
- The
moonbase_licensingmodule wired into a plugin via CMake +juce_add_module. - A single branded
ActivationConfig(src/Licensing.h) driving both the audio‑thread license gate and the activation overlay. - The processor as the licensing source of truth (a headless
ActivationController- a
std::atomic<bool>read on the audio thread), so gating works with the editor closed.
- a
- The module's brandable
ActivationComponentshown as a modal overlay from a Manage License button — no hand‑built activation screens. - Audio gated by license: the output is silent until the plugin is activated.
- A HALO‑grade native GUI: bundled fonts, a custom
LookAndFeel, custom knobs, and the signature animated grain‑field visual driven live by the (decorative) parameters.
DRIFT is mostly decoration wrapped around a small licensing core. If you are using
this as a reference, the complete strictly‑required surface is below — everything else
(the knobs, the grain field, fonts, LookAndFeel, the processor's atomic gate
plumbing) is DRIFT‑specific polish you can drop. In the source, the required bits are
marked with // [moonbase] REQUIRED and the rest with // [drift] decoration.
Build wiring — the only licensing‑specific lines in CMakeLists.txt:
include(FetchContent)
FetchContent_Declare(moonbase_cpp
GIT_REPOSITORY https://github.com/Moonbase-sh/moonbase-cpp.git
GIT_TAG <pinned commit or release tag>
SOURCE_SUBDIR modules) # populate only — don't add moonbase-cpp's root CMake
FetchContent_MakeAvailable(moonbase_cpp)
juce_add_module(${moonbase_cpp_SOURCE_DIR}/modules/moonbase_licensing)
target_link_libraries(DRIFT PRIVATE moonbase_licensing)
target_compile_definitions(DRIFT PRIVATE JUCE_USE_CURL=0) # use the module's zero-dep transport
if(APPLE)
enable_language(OBJC OBJCXX) # the module has a Security.framework Obj-C++ unit
endif()No brew / vcpkg / apt packages, no OpenSSL/curl. JUCE 8 only.
Configure — three required fields (src/Licensing.h); everything else on
ActivationConfig is optional branding:
ActivationConfig config;
config.endpoint = "https://your-tenant.moonbase.sh"; // REQUIRED
config.productId = "your-product"; // REQUIRED
config.publicKey = yourTenantPublicKeyPem; // REQUIREDOwn the controller in the processor, share it with the editor — one license, and gating that's correct whether or not the editor is open:
// AudioProcessor member:
moonbase::juce_integration::ActivationController license { config };
license.start(); // load + validate any stored license
// In createEditor(): the overlay shares the processor's controller (non-owning).
auto* editor = new ActivationComponent (processor.license);
// onClose -> dismiss(); resized() -> setBounds(); Manage button -> appear();Gate the audio off the controller's lock-free flag — no ChangeListener:
if (! license.licensedFlag().load())
buffer.clear(); // silent until activated…or use LicenseGate for a click-free fade on activate/deactivate (what DRIFT does):
moonbase::juce_integration::LicenseGate gate; // AudioProcessor member
void prepareToPlay (double sr, int) override { gate.prepare (sr); gate.reset (license.licensedFlag().load()); }
void processBlock (juce::AudioBuffer<float>& b, ...) override
{
gate.process (b.getArrayOfWritePointers(), b.getNumChannels(), b.getNumSamples(),
license.licensedFlag().load());
}applicationVersion is auto-filled from JucePlugin_VersionString in a plugin, so
telemetry reports the build version with no wiring. Everything else —
DriftLookAndFeel, DriftKnob, GrainField, MiniMeter, Branding.h, the bundled
fonts/logo — is pure DRIFT styling, unrelated to licensing.
Requires CMake ≥ 3.22 and a C++17 toolchain. JUCE 8.0.4 and the moonbase_licensing
module are both fetched automatically on the first configure (via CMake FetchContent),
so there are no git submodules — a plain clone is the whole setup.
git clone <this-repo>
cd <this-repo>
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build buildArtefacts land in build/DRIFT_artefacts/<config>/{VST3,AU,Standalone}/. There is
nothing to brew / vcpkg / apt install — the module uses OS‑native crypto
(Security.framework / CNG / system libcrypto). On Linux only, install libssl-dev
for libcrypto plus the usual JUCE X11/ALSA/FreeType packages (see .github/workflows/ci.yml).
scripts/run.sh # configure + build + launch DRIFT.app (macOS)
scripts/run.sh --clean # wipe build/ firstrun.sh only builds the Standalone. To test in a DAW, build + install the plugin
formats (COPY_PLUGIN_AFTER_BUILD copies them into your plugin folders):
scripts/install.sh # build + install VST3 (+ AU on macOS)
scripts/install.sh --validate # ...then run auval on the AU (macOS)Installs to ~/Library/Audio/Plug-Ins/VST3/DRIFT.vst3 and
~/Library/Audio/Plug-Ins/Components/DRIFT.component (macOS), or ~/.vst3 (Linux).
Both scripts auto-pin the macOS SDK to the active Xcode (so JUCE's juceaide
compiles even when newer Command Line Tools SDKs are installed); a raw cmake
invocation may need DEVELOPER_DIR / SDKROOT set manually.
- Launch the standalone (
scripts/run.sh). With no stored license the activation overlay appears and the plugin is locked — audio output is silent. - Click Activate online → your browser opens the Moonbase activation page for the Corino demo tenant.
- Sign in / fulfil the activation in the browser.
- Within ~1 second the overlay dismisses and audio un‑mutes (a click‑free
LicenseGatefade). - Quit and relaunch — activation is skipped: the stored license at
~/Library/Application Support/Corino/DRIFT/license.mb(platform‑appropriate path) is validated on startup. - Re‑open the overlay from the Manage License button to inspect license details, or Deactivate to release the seat on the server and re‑lock the plugin.
In a DAW, install the plugin (scripts/install.sh) and do the same from the VST3 / AU —
gating is driven by the processor, so it behaves identically with the editor closed.
Everything lives in src/Licensing.h. It targets the Corino demo
tenant (corino-demo.moonbase.sh, product drift). The RSA public key is per‑tenant
(it signs every product's tokens), so it's the same key HALO embeds.
To ship against your own tenant or product, swap endpoint / productId / publicKey
for the values from your Moonbase dashboard. A wrong key/product does not break the
build — activation simply routes to the Welcome/Error screen until corrected. The
validated license is cached at ~/Library/Application Support/Corino/DRIFT/license.mb
(platform‑appropriate path), so relaunching skips activation.
moonbase-cpp is pulled via CMake FetchContent (the same mechanism as JUCE) and pinned
to a specific commit on the module's upstream main branch
(PR #14 is merged). Only the
modules/moonbase_licensing folder is consumed — SOURCE_SUBDIR modules stops
FetchContent from adding moonbase-cpp's root CMake (and the SDK's OpenSSL/CURL target).
To move to a newer commit (or a release tag once the module ships in one), bump GIT_TAG
in CMakeLists.txt and re‑configure:
# edit GIT_TAG in CMakeLists.txt, then:
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release # re-fetches at the new pinTo hack on the module against a local checkout without touching the pin, point FetchContent at it:
cmake -B build -DFETCHCONTENT_SOURCE_DIR_MOONBASE_CPP=/path/to/moonbase-cpp ...ci.yml runs on every push/PR and builds on macOS (VST3/AU/Standalone), Windows
(VST3/Standalone) and Linux (VST3/Standalone), uploading the built bundles as workflow
artifacts. Both JUCE and the licensing module are fetched during configure, so checkout
needs no submodule step and no token (moonbase-cpp is public).
release.yml builds the plugin bundles and publishes them straight to the Moonbase tenant
(corino-demo.moonbase.sh, product drift) as a new release, following the
GitHub Actions product‑release recipe.
It ships macOS (arm64) and Windows (x64) and attaches both; Linux is built in CI
but not published (add another build-* job + downloads entry to change that).
- In the Moonbase tenant dashboard, create a Merchant API key with permission to manage product downloads.
- In this repo → Settings → Secrets and variables → Actions, add a secret named
MOONBASE_API_KEYcontaining that key. - Confirm
MOONBASE_TENANT_HOST/MOONBASE_PRODUCT_IDat the top ofrelease.ymlmatch the config insrc/Licensing.h(default:corino-demo.moonbase.sh/drift).
git tag v1.0.1
git push origin v1.0.1The workflow resolves the version from the tag, builds and zips the bundles per platform
(ditto --keepParent on macOS so the bundle structure + xattrs survive), uploads each via
POST /api/downloads/prepare → PUT, then publishes a single release with both downloads
via POST /api/products/drift/releases/new. You can also run it manually from the
Actions tab — supply the version (1.2.3) and choose whether to publish immediately or
leave the release as a draft for review in the dashboard.
CMakeLists.txt # FetchContent JUCE + moonbase_licensing module, juce_add_plugin
resources/fonts/ # Space Grotesk, Inter, JetBrains Mono
resources/logo/drift.svg
scripts/run.sh # configure + build + launch Standalone (macOS)
scripts/install.sh # build + install VST3 (+ AU on macOS), --validate runs auval
src/
PluginProcessor.{h,cpp} # licensing source of truth: ActivationController + atomic gate + LicenseGate
PluginEditor.{h,cpp} # plugin UI + ActivationComponent overlay (Manage License)
Licensing.h # [moonbase] REQUIRED ActivationConfig (endpoint / productId / publicKey)
Branding.h # palette + font names + background painter
DriftLookAndFeel.{h,cpp}# bundled-font wiring + custom controls
ParamIDs.h # decorative parameter IDs
ui/
DriftKnob.{h,cpp} # custom rotary knob
GrainField.{h,cpp} # animated grain-field visual
MiniMeter.{h,cpp} # footer IN/OUT meter
DRIFT's visual identity is the cool counterpart to HALO's warm amber: an aqua/teal accent
suspended in a deep blue‑black field — the "cloud of grains" between reverb, delay and
synthesis. It's defined in src/Branding.h:
- Background — charcoal‑blue vertical gradient (
#0e1318→#070a0d) with teal and indigo radial washes. - Accent — aqua/teal
#5fd4cf(bright#9ff0ea, deep#2c8f8a). - Foreground — cool off‑white
#eef4f5. - Type — Space Grotesk (display), JetBrains Mono (technical labels), Inter (body).
The signature element is the animated grain field (src/ui/GrainField.*), driven
live by the decorative parameters.
This sample is MIT‑licensed (see LICENSE). JUCE 8 is licensed separately —
this project consumes JUCE under the GPLv3 path implicit in FetchContent; see JUCE's
licensing terms. The Moonbase module is MIT‑licensed. Bundled fonts ship under their
respective SIL Open Font Licenses.
