Rubato Composer integration for Mazzola's mathematical music theory
/plugin marketplace add plurigrid/asi/plugin install plurigrid-asi-skills@plurigrid/asiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Integrates Rubato Composer - Gérard Milmeister's Java implementation of Guerino Mazzola's mathematical music theory. The software embodies the Topos of Music framework with Forms, Denotators, and a Scheme interpreter.
Rubato Composer implements 40 classes in org.rubato.math.yoneda:
Core Structures:
├── Form.java - Abstract base for musical types
├── Denotator.java - Musical objects (notes, chords, scores)
├── Morphism.java - Transformations between forms
├── MorphismMap.java - Functorial mappings
│
├── LimitForm.java - Categorical limits (product types)
├── ColimitForm.java - Categorical colimits (sum types)
├── ListForm.java - Sequence types
├── NameForm.java - Named reference types
│
├── LimitDenotator.java - Instances of limit forms
├── ColimitDenotator.java - Instances of colimit forms
├── ListDenotator.java - Sequences of denotators
└── Diagram.java - Categorical diagrams
Rubato includes a full Scheme interpreter with musical primitives:
// From org.rubato.scheme
SDenotator.java - Denotators as Scheme values
SForm.java - Forms as Scheme values
SExpr.java - S-expression base class
Parser.java - Scheme parser
RubatoPrimitives.java - Musical operations
;; In Rubato's Scheme dialect
(define note (make-denotator "Note" pitch-form 60))
(define chord (make-list-denotator "Chord" (list note1 note2 note3)))
;; Morphism application
(apply-morphism transposition chord 7)
# Our ACSets correspond to Rubato Forms
@present SchNote(FreeSchema) begin
Pitch::Ob
Duration::Ob
Onset::Ob
Note::Ob
pitch::Hom(Note, Pitch)
duration::Hom(Note, Duration)
onset::Hom(Note, Onset)
end
# Rubato equivalent:
# LimitForm("Note", [pitchForm, durationForm, onsetForm])
# ACSet instance = Denotator
note_acset = @acset Note begin
Pitch = [60, 64, 67]
Duration = [1.0, 1.0, 1.0]
Onset = [0.0, 0.0, 0.0]
Note = [1, 2, 3]
pitch = [1, 2, 3]
duration = [1, 2, 3]
onset = [1, 2, 3]
end
# Transposition as ACSet morphism
function transpose(notes::ACSet, semitones::Int)
map_parts(notes, :Pitch) do p
p + semitones
end
end
Rubato's plugin system (Rubettes) maps to our skills:
| Rubette | music-topos Equivalent | Description |
|---|---|---|
| ScorePlay | sonic_pi_renderer.rb | Score playback |
| BigBang | maximum_dynamism.rb | Gestural composition (MVC) |
| MetroRubette | Free Monad patterns | Metric structure |
| WallpaperRubette | gay_neverending.rb | Morphism-based tiling |
| MeloRubette | skill_sonification.rb | Melodic analysis |
// BigBangRubette.java - Gestural composition
BigBangModel model; // Composition state
BigBangController controller; // User interaction
BigBangSwingView view; // Visualization
// → maps to MaximumDynamism::DerangementConfig
// WallpaperRubette.java - Florian Thalmann
// Creates wallpapers using morphisms applied to power denotators
List<ModuleMorphism> morphisms;
PowerDenotator output = getUnitedMappedDenotators(input, morphisms);
// → maps to GayNeverending color spiral
# Clone (already done)
cd ~/worlds/o
gh repo clone rubato-composer/rubato-composer
# Build
cd rubato-composer
ant
# Run
java -jar rubato.jar
Rubato can export to MIDI, which SuperCollider can receive:
;; In Overtone/our stack
(def rubato-midi (midi-in "Rubato"))
(on-event [:midi :note-on]
(fn [e]
(play-note (:note e) (:velocity e)))
::rubato-handler)
Export Rubato scores to OSC:
# sonic_pi_rubato_bridge.rb
require 'osc-ruby'
client = OSC::Client.new('localhost', 4560)
def play_rubato_score(denotators)
denotators.each do |d|
client.send(OSC::Message.new('/trigger/synth',
d[:pitch], d[:duration], d[:onset]))
end
end
| Rubato State | TAP | Color |
|---|---|---|
| Composing | LIVE (+1) | Red |
| Analyzing | VERIFY (0) | Green |
| Archived | BACKFILL (-1) | Blue |
TOPOS(Music) = Presheaves over Form Category
Forms = Objects (types)
Denotators = Generalized elements (instances)
Morphisms = Natural transformations
Performance = Score × Tempo × Dynamics × Articulation
Where:
Tempo: ℝ⁺ → ℝ⁺ (time deformation)
Dynamics: ℝ → [0,1] (amplitude envelope)
Articulation: [0,1] (attack/release shaping)
just rubato-build # Build Rubato Composer
just rubato-run # Launch GUI
just rubato-scheme # Start Scheme REPL
just rubato-export # Export to MIDI/OSC
MAZZOLA_TOPOS_OF_MUSIC_GUIDE.md - Mathematical frameworkGENESIS_QUERY_PATTERN.md - How we discovered thisacsets/SKILL.md - ACSet implementationOVERTONE_TO_OSC_MAPPING.md - Sound bridge