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

150 lines
8.6 KiB
Markdown

# 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](assets/editor.png)
## 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](fl-studio.md).
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](theory/README.md).
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:
```sh
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](../development.md) for checks, dependencies, architecture, and
[releases](../releases.md) for independent release tags.
## Design and references
[Theory findings and implemented design](theory/README.md) connect the research
to practical controls. [Implementation plan](implementation.md) records the musical and technical
choices. [Devath reference measurements](research/devath.md) 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.