Files
bass-foundry/docs/rivet/README.md
T
nvrl 15853e61ac
Check and Windows preview / check (patina) (push) Successful in 2m20s
Check and Windows preview / check (rivet) (push) Successful in 1m38s
Check and Windows preview / previews (push) Successful in 1m6s
Check and Windows preview / windows (push) Successful in 1m50s
Independent plugin release / publish (push) Successful in 8s
Independent plugin release / plan (push) Successful in 7s
Independent plugin release / build (push) Successful in 2m21s
restructure
2026-11-05 23:58:00 +01:00

8.6 KiB

Rivet

Rivet joins short motifs into connected musical phrases, like a fastener joining individual pieces. Formerly Motif Storyboard; current version 0.3.0.

A Rust composition companion for an experienced producer developing their own melodic ideas. Version 0.3 explores rhythm, space, contour, harmonic arrivals, and returns, with reusable gestures, branching ideas, and two sound roles.

Rivet editor

Write with it

  1. Import a monophonic MIDI motif of up to two bars in 4/4, or load the demo.
  2. Choose a task: Develop the motif, Write an answer, Make room, or Find a return. Choose a settled or open ending and a four/eight-bar length.
  3. Decide what defines the idea. Keep groove fixes note positions and lengths; Keep contour protects the direction of movement, allowing flattened steps at register limits. Click source notes to lock the whole note, pitch only, or rhythm only. Clicking uses the currently selected lock mode. Locks and identity constraints take precedence over the proposed transformations.
  4. Optionally open Harmony and import a chord/bass MIDI track (up to eight bars), or create and edit a four-chord progression. Imported overlapping notes become pitch-class regions with the actual lowest held pitch; the tool does not guess chord roots or chord names. Empty regions remain gaps, and short contexts repeat. Harmony guides strong notes and arrivals; the preview plays the melody only. Supplied chord tones may extend beyond the selected scale.
  5. Explore alternatives. A deterministic pool of eight transformation families supplies up to three distinct proposals, selected for the task and differences in rhythm, density, duration, and pitch. Fully constrained motifs may yield fewer than three; cosmetic velocity differences do not count as new ideas.
  6. Select a proposal and pin its two-bar sections. Select another to fill the remaining sections, or explore another take. Preview and export the combined phrase from the fixed bottom toolbar. Keep a combined result to retain it independently of new proposals; undo/redo switches the kept result and its previous value. Individual proposals and kept results can also be exported.

The opening quotation stays intact. Later sections use displaced entries, repeated pickups, fragments, subtraction, short/long answers, changed endings, register contrast, and returns. These are compositional suggestions, not promises of an emotion or of commercial originality. Different seeds choose structured alternatives; they do not independently randomize every pitch.

Pins survive task/seed/harmony changes and regeneration. Changing the motif, its locks, or the phrase length clears pins. Pinned sections override newly proposed material. Unsafe boundaries in legacy candidates are rejected instead of truncating sustained notes. Changing generation inputs clears current proposals while retaining kept work.

Audition and commit

Internal voice provides two simple reference voices. MIDI output sends notes and optional CC curves on the configured channels to routed external synths and mutes the internal voice. Solo defaults to channel 1. Looping is optional and enabled for new sessions. When audition is already running, another selection waits until the next two-bar boundary or current phrase end. Note-offs precede repeated same-pitch note-ons; stop, replacement, loop boundaries, reset, restoration, and mode changes release active output notes on the processing thread. Queued auditions are canceled by Stop.

Host tempo follows tempo, with the local BPM as fallback. It does not align the initial audition to the DAW's song position: start it at the desired point in the project loop. Host start never initiates audition; host stop silences it. Exported MIDI is in musical ticks and carries the local BPM as its tempo event. Native OS MIDI drag-out is not implemented; export files to commit a phrase. See FL Studio setup and acceptance checks.

Open Gestures, moves, and branches to save a source or selected two-bar section with its performance choices. Export/import a gesture library between projects. Save a branch before experimenting; restore any branch and make a new child with subtraction, a delayed entry, longer gates, or transposition. Moves respect pins and locks, reject unsafe overlaps, and report when constraints leave nothing to change. Libraries and histories each hold up to 16 entries; remove a gesture or a leaf branch to make room.

Open Sound roles and expressive gestures to pass existing notes between two patches: alternate events, alternate question/answer bars, or divide strong beats from replies. These modes distribute a monophonic phrase rather than generate a second independent melody. Assign separate MIDI channels and explicitly map each optional CC lane to a synth macro. Curves are normalized over the whole phrase, with editable points and rise/fall/arch/pulse starting shapes. Names describe your intent; the plugin does not infer feelings.

Patch profiles set register offset, gate, velocity, and estimated attack/release. MIDI audition uses a short warmup for early triggers. Re-audition after a tempo change to recompile millisecond offsets. Compensation estimates trigger timing; it does not measure patch latency or model its sound. Default export retains musical positions; compensated export adds one bar of lead-in. Role tracks carry names, channels, and CC curves. Stop resets mapped controllers to their chosen stop values. Internal audition does not reproduce mapped timbre. See the theory and producer workflow.

Sessions save inside the host project and can be saved/loaded as JSON. Version-1/2 sessions and the original host field identifier remain supported; older sessions retain one-shot audition. New sessions persist harmony, task, lock modes on notes, pins, proposals, kept history, gestures, branches, patch profiles, CC curves, and audition settings. JSON state is bounded at 16 MiB; gesture libraries at 2 MiB. File export/save refuses to silently overwrite an existing file.

Build and offline preview

Run from the repository root:

cargo run -p rivet-preview -- demo /tmp/rivet-demo
cargo run -p rivet-preview -- develop motif.mid 0 /tmp/phrase
cargo run -p rivet-preview -- develop motif.mid 0 /tmp/with-chords chords.mid 0
cargo run -p rivet-preview -- session saved-session.json /tmp/rendered-session
python scripts/build-plugin.py --plugin rivet --target x86_64-pc-windows-gnu

The preview writes source/candidate MIDI, a session JSON, and WAV using the same engine as the plugin. Track indices exclude conductor-only tracks and start at zero. Optional harmony arguments accept a separate polyphonic MIDI file. See development for checks, dependencies, architecture, and releases for independent release tags.

Design and references

Theory findings and implemented design connect the research to practical controls. Implementation plan records the musical and technical choices. Devath reference measurements document analysis of the seven supplied FLACs, with reproducible plots and explicit limits. Original reference audio is excluded from source distribution.

  • rivet-core: musical model, harmonic context, structured proposals, section composition, session migration, and bounded playback clips.
  • rivet-midi: bounded SMF 0/1 import/export. Rejects SMPTE, unsupported meters, incomplete notes, and timing not exactly representable at 960 PPQ. Reports ignored controllers/pitch bends. Polyphonic tracks work as harmonic context; motif import requires monophony.
  • rivet-app: worker jobs, revision handling, bounded queues, sample-accurate preview/MIDI scheduling, and Windows/Zenity dialogs.
  • rivet: CLAP wrapper, host persistence, editor, and standalone.

Tests cover musical constraints/diversity, harmony, legacy state, section seams, MIDI round trips, sample timing, looping, queued switches, note releases, and zero allocation/deallocation during rendering and queued clip replacement. The CLAP ABI test verifies discovery, note-output port exposure, state restoration, and silent startup at several sample rates and buffer sizes.

Existing projects

The name, Cargo packages, source paths, and output filename have changed. The CLAP ID io.storyboard.motif, story-session-v1 host field, and session JSON format are preserved. Rescan FL Studio after replacing the old plugin file with Rivet.clap; remove the old copy from scanned folders to avoid duplicate instances with the same ID. Project recall still needs a check in the target host.