OOLOI.ORG
Menu

OOLOI

An Organism Evolved.

OVERVIEW

DOCUMENTATION

NEWSLETTER

Hash-Consing

25/9/2025

0 Comments

 
Picture
Musical scores are full of repetition. In a symphony, middle C can appear thousands of times, quarter notes dominate, and the same staccato mark is scattered across every instrument. Most notation software allocates a separate object for each of these occurrences. That means thousands of identical objects, all taking memory and I/O bandwidth for no reason.

Ooloi doesn't.

With ADR-0029, we have implemented selective hash-consing: identical immutable musical objects are represented by the same instance. The same C4, the same staccato, the same quarter note: one object, shared system-wide.

Why "Selective"?

Not everything benefits. A forte marking may appear only a handful of times; a slur always connects specific endpoints. Caching those adds overhead without real gain. So the system targets high-frequency cases (pitches, rests, chords, common articulations) and ignores the rest.

What this changes

  • Memory footprint collapses: a score that would allocate hundreds of thousands of objects now reuses a fraction of them.
  • File sizes shrink: less redundancy on disk and across the network.
  • I/O accelerates: save/load no longer bottleneck on repeated data.
  • GC pressure drops: fewer allocations, less churn.
  • Scalability improves: orchestral and contemporary scores fit comfortably in memory.

All of this is transparent. Musicians won't 'use' hash-consing; they'll just notice that large works open, scroll, and save without drama.

Why it works here

In mutable architectures, shared objects are a trap: one stray modification contaminates every reference. Defensive copying and locks erase any performance benefit. In Ooloi, immutability is the rule. Sharing is safe. No copies, no locks, no bugs.

This isn't the kind of feature that makes a demo screenshot. It's one of the architectural foundations that decides whether the system will still perform when you open Mahler's 8th or La terre est une homme.

It took days to implement. That's the difference Clojure makes.
Picture
0 Comments

The Rendering Pipeline: Ooloi's Core Architecture

23/9/2025

0 Comments

 
Picture
Finishing the statistics infrastructure naturally led to thinking about the next architectural milestone: the rendering pipeline. This is the mechanism that determines what happens when someone clicks into a score to add a note, and how that change propagates through the system.

The design is complete. That in itself is an important milestone, as this is the very foundation on which Ooloi's performance ultimately depends. Everything hinges upon it.

Why a Pipeline?

Picture
Traditional notation software recalculates entire scores when a single element changes. Dense passages in works like Strauss's Elektra bring systems to a halt because every operation is sequential and single-threaded. The reason for this is that parallelism is very difficult to do with mutable state, which is the traditional approach. Scalability often becomes an issue, with diminishing returns as a result.

Ooloi takes the opposite approach and chooses the Clojure way instead, with immutable state. With this, it is comparatively easy to distribute formatting work across all available CPU cores and use them fully and linearly.

Every user action – whether adding a single note or adjusting spacing – thus becomes part of a coordinated cascade where each stage can run in true parallel across all available cores.
​
The goal is straightforward: responsive editing even in the heaviest repertoire.

​Five Stages

ADR-0028 specifies the pipeline in five stages, separating connecting from non-connecting elements and applying a clear fan-out/fan-in pattern.
  1. Minimum Widths (Fan-out): Each measure independently calculates spatial requirements – collision boundaries only. Results are immutable and persist until the content changes.
  2. Vertical Raster (Fan-in): The MeasureStackFormatter collects widths, generates result rasters, and records both minimum and ideal widths. This prepares the ground for spacing optimisation.
  3. Non-Connecting Elements (Fan-out): Independent symbols – noteheads, accidentals, articulations, dynamics – are prepared in parallel. They don't need finalised atom positions.
  4. Discomfort Minimisation: Iterative optimisation adjusts widths and system breaks to reduce proportional distortion. No layout changes occur after this stage. From here on, positions are fixed.
  5. Connecting Elements​: Slurs, ties, beams, hairpins, and glissandi are drawn only once final positions are known. Sequential coordination ensures continuity across measures and systems.

This separation allows Ooloi to exploit parallelism where possible and enforce order where necessary.

​Plugins as First-Class Citizens

Picture
Formatting in Ooloi is plugin-driven. Core elements such as notes and beams are implemented through the same interfaces available to extensions.
​
Plugins can participate in different stages depending on their needs:
  • Spacing hook (Stage 1) for collision boundaries
  • Paint hook (Stage 3) for independent elements
  • Connect hook (Stage 5) for elements spanning multiple atoms

Simple articulations may use only the first two; beams may require all three. This uniform model ensures extensibility without compromising performance.

Convergence by Discomfort

The optimisation engine measures deviation from ideal proportions across measures, systems, and pages. Improvements multiply: small gains in multiple places compound into significant overall reductions. Hard constraints such as manual breaks provide natural stopping points.
​
This replaces arbitrary iteration limits with a principled measure of quality.

​Parallelism and Responsiveness

Claypoole provides efficient thread-pool execution, delivering significant speed-ups over built-in Clojure parallelism. STM transactions keep operations atomic while allowing concurrency inside each stage. Cooperative cancellation ensures that rapid user input remains responsive.
​
The system treats a single user as a 'collaboration network of one'. The same infrastructure that supports multi-user editing ensures smooth interaction for individuals.

​Where This Leads

Picture
This pipeline is the structural core that should make scrolling through Elektra or Ligeti's Requiem as fluid as editing a Gnossienne by Satie.
​
The specification is complete. Implementation begins as soon as the current phase closes. Ooloi's promise of responsive, professional-scale notation depends on it.

​Scary stuff.


​Full specification: ADR-0028: Hierarchical Rendering Pipeline with Plugin-Based Formatters
0 Comments

Why Ooloi Leaves MIDI Behind

13/9/2025

0 Comments

 
Picture
Yesterday’s post was about pitch transposition in Ooloi: how an old Igor Engraver function (printed on a t-shirt, of all places) came back to life in a new context. That work didn’t just solve the mechanics of shifting notes up and down; it reopened the larger question of playback. How do you hear microtonality and advanced humanisation without drowning in technical workarounds?

In Igor, the answer was MIDI. Notes were split across channels, bent into place, reassigned constantly. The result worked, but at the cost of complexity: a “DNA soup” of allocations and pitch-bend tricks. Ingenious, but exhausting.

Ooloi makes a different choice.

With ADR-0027: Plugin-Based Audio Architecture, we draw a line: no MIDI output in the core, no audio generation in the backend. Playback is done entirely through plugins in the frontend. If you want VST/AU instruments, SoundFonts, OSC, or any other output path, you install a plugin. The backend remains what it should be: musical data, collaboration, structure.

This is not just simplification, it’s liberation.
  • Microtonality is handled directly in the data model, then played back by plugins without channel gymnastics.
  • Humanisation is no longer bound to 7-bit controllers; plugins can drive modern sample libraries with full parameter precision.
  • Collaboration becomes clearer: the backend never streams audio, never mangles MIDI, never compromises. Each client handles its own sound.

Put bluntly: we no longer need MIDI as an output protocol. It served its time. For professionals who need nuanced playback, orchestral realism, or contemporary techniques, we now have better tools: VST/AU plugins and beyond.

That said, MIDI output isn’t forbidden. If anyone needs it, a frontend plugin can provide it. For tonal music it will work fine. But if you want advanced humanisation or microtonality, you’ll inherit the need for all the old machinery: channel allocation, pitch-bend acrobatics, the DNA soup. That’s exactly why Ooloi itself doesn’t touch it.

The logic is simple: Ooloi’s core manages music, not sound. Plugins handle playback, and in doing so, they do it better than MIDI ever could.

The DNA soup is gone. What remains is clean, modern, and far more powerful.
0 Comments

Announcing the Ooloi Newsletter

6/9/2025

0 Comments

 
Picture
Ooloi is moving fast. Architectural decisions, implementation milestones, and the long road toward open-source release deserve a channel that isn’t buried in blog posts or scattered across updates.

The Ooloi Newsletter is that channel. It’s for composers frustrated with the lag of existing software, musicians curious about what modern architecture makes possible, educators and publishers planning future workflows, and developers who want to see Clojure’s STM, transducers, and gRPC applied directly to real musical problems.

This isn’t marketing. There’s nothing to hype, no metrics to chase. It’s progress – the daily work of turning musical thinking into software design. Updates arrive when there’s something real to report: once or twice weekly in active phases, slower during architectural deep work.

Expect honest accounts of what’s been built, what broke, and why decisions were made. Technical when it illuminates music, musical when it drives architecture. No jargon for its own sake, and no dumbing down.

If that sounds useful, subscribe at buttondown.com/ooloi.

The thread from FrankenScore to Ooloi continues. You’re welcome to follow it.

0 Comments

ADR 0025: Server Statistics Architecture

25/8/2025

0 Comments

 
The Ooloi server must of course also have comprehensive introspective statistics, as it can be deployed in several ways and has a structure which is perhaps a bit unusual. The combination of STM-wrapped gRPC API calls with server-to-client event streaming creates some operational challenges: things like per-client queue overflow behaviour and collaborative editing session patterns.

Hence this new ADR on server statistics, which takes a two-level approach: server-wide aggregates that survive client churn, plus detailed per-client metrics for operational visibility. Oh, and it interfaces with Grafana, Prometheus, and friends straight out of the box via simple HTTP endpoints.

Halfway through the stats implementation now. It's been a productive weekend.
Picture
0 Comments

Ooloi Server Architecture Documentation

22/8/2025

0 Comments

 
Picture
I've just published the Ooloi Server Architectural Guide documenting the backend implementation and its characteristics.

The server combines Clojure's STM with gRPC for concurrent access patterns, uses a unified protocol design to eliminate schema complexity, and integrates real-time event streaming for collaborative editing.

​The guide covers the architecture, technical implementation, performance characteristics, and deployment scenarios for anyone interested in the server architecture details.

And now, back to the frontend client implementation...
0 Comments

From the Ooloi Front: Towards Hello World

3/8/2025

0 Comments

 
Picture
Right. Quick update from the development trenches.

When I completed Ooloi's backend engine in July, starting work on the frontend interface revealed the anticipated cascade of architectural requirements that needed systematic resolution first.

Here's what emerged, in order:

1. Collaborative Undo/Redo Architecture (ADR-0015)
Thinking about frontend-backend relationships immediately raised the question: how does undo/redo work in a multi-client, distributed collaborative setup? The answer required a three-tier architecture separating backend piece changes (coordinated via STM) from frontend UI changes (local to each client).

2. Universal Settings Architecture (ADR-0016)
The insight that there should be no global application settings, only per-piece settings living inside each piece, led naturally to implementing settings not just on the piece level, but across all levels of the hierarchy. Any entity – piece, musician, staff, pitch – can now have configuration attributes via a unified defsetting macro with lazy storage and automatic VPD support.

3. Component Lifecycle Management (ADR-0017)
Multi-scenario deployment demanded rock-solid system architecture using Integrant. This needed to be in a stable architectural form – wiring, lifecycle boundaries, failure modes – before setting up the actual components with proper dependency injection, partial failure handling, structured error codes, the full production suite.

4. Automated gRPC Generation (ADR-0018)
With component architecture sorted, I could tackle the actual gRPC implementation: automating API endpoint generation for native Java interop across hundreds of methods, plus bidirectional communication for real-time collaboration. Manual implementation at this scale would be architecturally impossible.

5. In-Process Transport Optimisation (ADR-0019)
Combined deployments (frontend and backend in same process) were using unnecessary network transport. Implementing automatic in-process gRPC transport delivers 98.7–99.3% latency reduction whilst preserving external monitoring capabilities.

6. TLS Infrastructure (ADR-0020)
Secure connections are essential for distributed deployments – conservatory intranets, corporate environments, cloud SaaS situations. Auto-generating certificates with full enterprise capabilities makes this transparent whilst supporting everything from development to production.

7. Authentication Architecture (ADR-0021)
Finally, distributed deployments require comprehensive authentication and authorisation. Pluggable JWT-based providers scale from anonymous sessions to enterprise LDAP integration. This is fully designed and will be implemented as deployment scenarios require.

Current Status: About 95% of the above is implemented, tested, and production-ready.

Next Steps: Finish the auto-generated gRPC Java interop interface, then create an actual frontend client of the 'Hello World' variety and ensure it runs and communicates across all deployment scenarios.

The rather encouraging discovery throughout this process was how readily the existing functional architecture accommodated these enterprise concerns. Vector Path Descriptors naturally supported universal settings. STM transactions elegantly handled collaborative undo operations. The component system absorbed authentication providers without strain. When features like collaboration or security slide cleanly into place, it's not luck – it means the architecture wanted them there. That's what sound foundations do.

Worth noting: collaboration isn't something tacked on later. It's integral to the architecture from the ground up.
​
Right. Back to the gRPC generator.
0 Comments

I Couldn't Wait Any Longer: Complete Ooloi Documentation Released

6/7/2025

0 Comments

 
Picture
​I've been saying I'm itching to open source Ooloi, but waiting for the complete software felt increasingly artificial. The documentation tells the real story – twenty-five years of architectural evolution from Igor Engraver through AWS systems thinking to this closure in Clojure.

So here it is: the complete Ooloi documentation collection, released publicly ahead of the software itself.
What you'll find:
  • Comprehensive guides teaching advanced Clojure through musical problems
  • Complete architectural decision records showing our thinking
  • The timewalker guide (with three Rocky Horror references, naturally)
  • Real functional programming education through meaningful domain examples

This represents my attempt to walk the talk after critiquing FP drawbridge syndrome. These guides serve dual purpose: they document sophisticated music notation architecture whilst teaching functional programming concepts through examples that actually matter.

The timewalker guide alone demonstrates transducers, lazy sequences, and functional composition through orchestral score traversal. The polymorphic API guide teaches multimethods through musical type systems. The concurrency patterns show STM coordination through collaborative editing.

Twenty-five years of thinking, distilled into something that I hope proves useful beyond music software. The architecture is complete; the foundations are solid. Now you can see why I've been eager to share this work.

An organism evolved, indeed.
​
Explore the complete documentation: https://github.com/PeterBengtson/Ooloi-docs

​/Peter
0 Comments

Booooring, Franz?

10/9/2024

0 Comments

 
Picture
No, documentation doesn't have to be boring. Well, it can of course be a soul-numbing, Kafkaesque exercise, but then, can't everything?

In an open-source project, good documentation is a must; everything needs to be explained and discussed properly for the benefit of all interested, and particularly for collaborators.

And not writing documentation in a group endeavour will land you in precisely the situation Josef K enjoyed so very much. Even in agile Prozesse – it's a myth that agile discourages documentation. It's all about the appropriate level. But then, isn't it always?

Ultimately, writing – and reading – documentation is all about the proper conservation of energy. It's just a question of finding the point where the curves intersect.

Anyway, here are a few additions to the Documentation section you might like. Feel free to evaluate them as lazily as you wish:

Architecture Decision Log
  • Now expanded with a bunch of additional ADRs.

Backend src README
  • Read all about it! Well, perhaps not all about it, but at least about the backend architecture, code organisation, principles, conventions, and of course the general programming paradigm.

Development Plan
  • Quod factum est, quod fit, quod fiet.
​
​License
  • Mozilla Public License (MPL) 2.0, with a couple of small twists.

Code of Conduct
  • Our Code of Conduct. Because not having one is being naive.
0 Comments

Architectural Decision Records (45 rpm)

2/9/2024

0 Comments

 
Picture
An Architecture Decision Record (ADR) is a point-in-time document that records architectural decisions and the reasoning behind them. And since communicating architectural ideas clearly to collaborators is extra important in open-source, I've just added a bunch of ADRs to the Documentation page.​

​They cover various aspects of the FrankenScore architecture, from high-level design decisions to specific technical choices. They are:
​
  • ADR-0000: Choice of Clojure as the Primary Programming Language
  • ADR-0001: Separation of Frontend and Backend into Distinct Clojure Applications
  • ADR-0002: Adoption of gRPC for Communication Between Frontend and Backend
  • ADR-0003: Integration of Plugins as a Core Architectural Component
  • ADR-0004: Implementation of Software Transactional Memory (STM) for Concurrency
  • ADR-0005: Selection of JavaFX and Skija for the Frontend GUI
  • ADR-0006: Adoption of SMuFL (Standard Music Font Layout) for Music Notation
  • ADR-0007: Implementation of Nippy for File Persistence
  • ADR-0008: Implementation of Vector Path Descriptors (VPDs)
  • ADR-0009: Implementation of Real-Time Collaborative Features

0 Comments

    Author

    Peter Bengtson –
    Cloud architect, Clojure advocate, concert organist, opera composer. Craft over commodity. Still windsurfing through parentheses.

    Search

    Archives

    January 2026
    December 2025
    November 2025
    October 2025
    September 2025
    August 2025
    July 2025
    June 2025
    April 2025
    March 2025
    September 2024
    August 2024
    July 2024

    Categories

    All
    Accidentals
    Alfred Korzybski
    Architecture
    Benchmarks
    Clojure
    CLOS
    Common Lisp
    DDD
    Death Of Igor Engraver
    Documentation
    Donald E Knuth
    Dorico
    Dynamic Programming
    Finale
    FrankenScore
    Franz Kafka
    Frontend
    Functional Programming
    Generative AI
    GRPC
    Igor Engraver
    Jacques Derrida
    JVM
    License
    LilyPond
    Lisp
    Localisation
    MIDI
    MPL 2.0
    MuseScore
    MusicXML
    Ooloi
    Ortography
    Pitches
    Playback
    Plugins
    Python
    QuickDraw GX
    Rendering
    Rhythm
    Rich Hickey
    Road Map
    Scheme
    Semiotics
    Sibelius
    Site
    Skia
    Sponsorship
    UI
    Umberto Eco
    Vertigo
    VST/AU
    Wednesday Addams

    RSS Feed

Home
​Overview
Documentation
About
Contact
Newsletter
Ooloi is an open-source desktop music notation system for musicians who need stable, precise engraving and the freedom to notate complex music without workarounds. Scores and parts are handled consistently, remain responsive at scale, and support collaborative work without semantic compromise. They are not tied to proprietary formats or licensing.
​
Ooloi is currently under development. No release date has been announced.


  • Home
  • Overview
    • Background and History
    • Project Goals
    • Introduction for Musicians
    • Introduction for Programmers
    • Technical Comparison
  • Documentation
  • About
  • Contact
  • Home
  • Overview
    • Background and History
    • Project Goals
    • Introduction for Musicians
    • Introduction for Programmers
    • Technical Comparison
  • Documentation
  • About
  • Contact