(feat): add Bassment multi-genre bassline app - #633
Draft
kosmar wants to merge 24 commits into
Draft
Conversation
Monophonic basslines on the shared genre axis with bassist Voice personas; includes minimal shared genre/groove/LED helpers for main. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
kosmar
marked this pull request as draft
August 8, 2026 21:00
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…bassment Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # faderpunk/src/app.rs
Co-authored-by: Cursor <cursoragent@cursor.com>
3 tasks
Co-authored-by: Cursor <cursoragent@cursor.com>
Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
Grooves, Chord Vamp and Bassment all render the genre axis with the continuous red→blue spectrum from led_fx, so the discrete per-genre chrome had no callers left. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
Shift+Tap walks a bass fill into the next bar's chord with a leading tone on the last hit; the Voice picks the contour (walk, arp, octave push, pedal) and high Density turns the gesture into a quiet pedal break. Shift+Hold lifts the register into a solo that re-rolls each bar and resolves on the next downbeat. Voice cycling moves to Long so Shift stays free; Previous Voice and the new Swing Dir enum live in the Configurator. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
…ndow A constant octave lift read as a wrong octave rather than a solo, so the lift now follows an arc: the phrase starts on a low anchor, peaks around 60 % of the bar and comes back down to land, with answer bars sitting lower for call and response. Peak height follows the Voice's octave span. Notes outside the playable window fold by octaves instead of clamping, which had collapsed every out-of-range note onto the same repeated pitch. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
… sign Jack and CV Dest spent two params on a choice that was really one: a CV In destination is dead while the jack drives CV Out, and vice versa. They become a single enum — CV Out, CV In Density, CV In Feel, CV In Reset — matching Grooves. Swing Dir folds into the sign of Groove max %, where a negative cap swings the offbeats early; only the magnitude still caps the Feel amount. The first twelve slots kept their types, so a stored blob folds forward on its own instead of resetting. Scene storage drops its vestigial `reversed` flag, which was already being read into a discard. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Note-generating apps each carried their own idea of Root and Scale, so the device-wide Key/Tonic — live on the Scene button plus Fader 4/5 — could not act as a transpose. This adds one shared place to resolve it: the normalized device Key, the tonic pitch class, a root retuned onto it keeping its octave, and a combined call that costs a single GlobalConfig copy instead of two. Resolving copies the whole GlobalConfig, so the module documents that callers must cache per bar or phrase rather than per note. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
Density behaved like Grooves' polyphonic model on a monophonic instrument, so raising it added noise instead of groove. Removes the reveal pass that filled deliberately empty steps, stops syncopation bias from inflating density and lets it colour ghost notes instead, keeps core hits instead of dropping them for air, and scales the Voice personas by Feel rather than driving them all toward the same busy ceiling. Chromatic approaches are limited to passing notes, microtiming is capped at two ticks so the bass sits near the kick, and the genre fill masks are sparser. Follow device tonic (default on) makes the global Tonic fader a live transpose: the pitch class comes from the device, the octave stays with Root, resolved once per bar so a new key lands on a bar line. Follow device scale defaults off because Scale carries the genre character. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
clippy::chunks_exact_to_as_chunks fires on the constant chunk size in the USB RX loop, and CI runs clippy with -D warnings, so main does not pass its own gate on a current toolchain. Feature branches have been carrying this same one-line fix inside unrelated app commits to stay green; landing it here means they no longer have to. as_chunks::<4>() yields &[[u8; 4]], so the packet indexing below is unchanged. The discarded remainder matches the previous behaviour: chunks_exact dropped a trailing partial packet too, and a USB MIDI bulk transfer is always a multiple of four bytes. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
Review feedback on ATOVproject#639: a dropped NoteOff hangs the note with no later message to correct it, and APP_MIDI_CHANNEL is shared by all 16 channels, so a busy neighbour can cause the drop. All three NoteOffs here run in the async voice task, where awaiting queue space costs at most a late NoteOff in this app's own loop. Drops the now-unused try_send_note_off from the branch copy of app.rs, matching ATOVproject#639. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
Same mutate+save API as ATOVproject#640 so WIP apps can call params.update now. Host AppState push stays out until the real writeback lands. Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
ParamStore::update polyfill (mutate+FRAM, no host push). Authored by an AI coding agent on behalf of kosmar. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
main(genre_palette,groove,led_fx) and register the appTest plan
Made with Cursor
Prerequisites
The platform pieces this app needs are under review as their own PRs, so that
each app PR stays small enough to review on its own.
Required — these APIs do not exist on current
main:App::clock_tickertry_send_*)ParamStore::update, so an app can write its own params back to the hostgenre_palette/groove/led_fxmodulesThis branch currently carries its own inline copy of the code in #638, #639, #640, #641.
Once those land it will be rebased to drop the duplicates, which shrinks this
diff to the app file plus its registry line.
Building any of this on a current Rust nightly also needs the toolchain fix in
#632.