|
Working on the Instrument Library – which has occupied the last few posts – I came to the point of editing staves inside instruments. That led, as it does, to clef representation; and clef representation led to the question of stave heights; and stave heights, once you look at them honestly, open onto a set of questions about what the numbers actually mean and who they serve. This is how development works: you pull on one thread and another appears. You pull that one and something else comes loose. The art is not pulling on all threads at the same time, or you end up with all yarn in one tangled clump. And when the threads start to proliferate, that is the signal to stop pulling and start architecting. So: stave sizes. One thread at a time. The stave space – the distance between two adjacent stave lines – is how Ooloi measures everything. Glyph dimensions, stem lengths, beam thicknesses, spacing: all of it derives from that single value, stored in millimetres. Not stave height; the space. The height is a consequence. I spent some time recently with the rastral table. A rastrum was a pen with five nibs, drawn across the copperplate page to produce a music stave in one stroke. The finite set of available pen widths produced nine standard stave heights, numbered 0 (largest) to 8 (smallest), each associated with a particular use. The pens are gone; the vocabulary remains. When an engraver says 'Rastral 3', the meaning is immediate: 7.0 mm, standard parts, piano. No conversion required, no mental arithmetic. It encodes decades of professional judgement about what is legible at what distance for which purpose. These values follow Gould (Behind Bars). Ross gives very slightly different numbers at some sizes – tenths of a millimetre – but Gould is the more recent authority and the more widely referenced in current practice.
Ooloi's sizing model is compositional. The base stave space propagates through a scaling chain – system, instrument, stave – where each level is a ratio against its parent. Change the base and everything follows. An ossia stave sits at two-thirds; a cue stave at three-quarters. The user works in ratios. The system reports the consequences in millimetres, with the approximate rastral equivalent alongside. That last part is where the investigation led somewhere I hadn't originally planned. Once I had the scaling chain and the rastral table in front of me, the obvious next question was: should Ooloi simply display the effective size, or should it also say whether that size is appropriate for what the layout appears to be? The answer, I think, is that it should. Wherever Ooloi reports an effective stave size – layout inspector, part configuration, print preview – the display will include a contextual assessment. Not just '7.4 mm (Rastral 2)' but whether that size makes sense for a flute part, or is slightly small for a piano reduction. The assessment will draw on published professional standards: MOLA puts 7.5 mm as the most readable size for orchestral parts, with anything below 7.0 mm unacceptable. The NZSO requires parts between 7.0 and 7.5 mm and rejects submissions outside that range. The software will tell you what it knows. It will not prevent you from doing anything. Rastral presets will appear on the base stave size control as named starting points, and again as targets when generating parts. Three places in total; nowhere else. The vocabulary will thread through the workflow without touching the architecture. A professional courtesy, not a load-bearing wall.
9 Comments
A recent exchange with Magnus Johansson in the comments on the Instrument Library post made me realise something worth saying at the top level, rather than buried in a reply thread. Magnus had compared Ooloi's bundled instrument library with Igor Engraver's and noticed that Igor's was substantially larger. The question was reasonable; the answer turns out to illuminate something fundamental about what Ooloi is actually for. But first, a correction. I keep encountering the claim – usually from AI systems summarising the project – that Ooloi is 'for advanced notation users'. This is wrong in a way that matters. The architecture is advanced; the user experience aims to be the opposite. The entire point of doing the hard work underneath is so that people don't have to do hard work on top. A tool that requires expertise to operate has failed at its job, regardless of how much expertise went into building it. Zero-effort playback is one example of what this means in practice. What Igor DidIgor Engraver shipped with Synth Matrices – text files that described every common hardware synthesiser on the market: available patches, controller mappings, pitch bend ranges, channel limitations, stereo position. When a user set up a score with, say, two flutes, a cor anglais, and strings, the Synth Matrix for their synthesiser took care of everything: patch selection, channel allocation, balance, panning. The user spent zero time on MIDI configuration. Zero. They dragged instruments from the library, wrote music, and heard the right sounds during input. This was 1996. Hardware synths, MIDI cables, 7-bit controllers. And yet a composer or arranger never touched a patch change, never drew a controller curve, never thought about channels. The system did it. We also collaborated with Johan Sundberg's Musical Acoustics department at the KTH Royal Institute of Technology, whose research had quantified things that musicians do instinctively: soloists anticipate the beat by about four milliseconds; phrase dynamics follow predictable contours; onset timing varies with articulation. Those findings went directly into Igor's playback engine. The result was that pressing Play on an orchestral score produced something that sounded like musicians playing, not a sequencer clicking through events. Now, I don't have Igor's code, I don't have any manuals, and I haven't run it in 25 years. The comparisons with Igor are inevitable when I write about playback, but Ooloi is not a resurrection. The ideas are the same kind of ideas I've always had, expressed through modern means. What follows is about where those ideas go next. The MIDI PrisonThat was nearly thirty years ago. What has changed since? Remarkably little, if you look at how most notation software handles playback. The underlying protocol is still MIDI – a 7-bit serial standard from 1983, designed for connecting keyboards to synthesisers over DIN cables. It has no concept of musical structure. It cannot distinguish between a quarter note and a dotted eighth tied to a sixteenth. It knows NOTE_ON, NOTE_OFF, velocity, and a handful of continuous controllers. That's the vocabulary through which an entire industry still attempts to communicate musical intent to sound-producing devices. The consequences are visible in every professional composer's workflow. You write a crescendo hairpin in your notation software. It looks correct on the page. You press Play. Nothing happens – because a hairpin is a musical concept, and MIDI has no musical concepts. To hear that crescendo, someone has to draw a CC11 expression curve in a DAW, by hand, matching the shape and timing of the hairpin. For every hairpin. In every part. This is what Hans Zimmer's assistants do. They sit in studios translating musical intent into controller data, note by note, gesture by gesture. If you are scoring a film with 40 staves, that translation is a full-time job for several people. If you're a composer working alone – which is to say, if you're almost any composer – it means choosing between hearing your music properly and finishing it on time. NotePerformer addressed this by sitting between notation software and playback, interpreting the score with a one-second lookahead buffer. It was a genuine breakthrough: finally, a tool that read musical markings and translated them into expressive performance. But NotePerformer is, by design, a workaround for deficiencies in a MIDI-based architecture. It exists because the notation software itself cannot do the translation. It patches over a gap that should not be there. Not Bypassing – Just Doing It RightWhen I first started describing Ooloi's approach to playback, I found myself reaching for the word 'bypassing'. Ooloi bypasses MIDI. Ooloi bypasses the DAW. And then I caught myself, because that word tells you something about how deeply the old paradigm has colonised our thinking. You only 'bypass' something that is assumed to be in the path. MIDI is assumed to be in the path because it has been in the path for forty years, and an entire industry has built its workflows around that assumption. Ooloi doesn't bypass MIDI. Ooloi simply doesn't use it. The distinction matters. Bypassing implies a workaround, a detour around an obstacle that remains in place. What Ooloi does is address the problem directly, using the technology available in 2026 rather than routing everything through a protocol designed when Margaret Thatcher was in her first term. Ooloi drives virtual instruments directly. No MIDI channel allocation. No patch changes. No 7-bit controller resolution. The notation engine communicates with sample libraries through their native host interfaces – VST3 parameters, note expression, articulation selectors – with full precision, in the plugin's own language. This is not a technical curiosity; it's the removal of an entire layer of translation that has stood between composers and their sounds for decades. OVID's MetamorphosesThe mechanism that makes this work is called OVID – the Ooloi Virtual Instrument Definition. OVID is the modern successor to Igor's Synth Matrices, but operating at a fundamentally higher level. A Synth Matrix described a hardware synthesiser: which patches lived where, how to select them, what the pitch bend range was. OVID describes a virtual instrument library: what playing techniques it offers, how to select them, how loud each articulation is relative to the others, how to compensate for onset timing differences between legato and staccato samples. The practical consequence is that Ooloi understands what it means to play an instrument, not merely what MIDI messages to send. Write 'pizz' above a string passage and Ooloi selects the pizzicato articulation from your sample library. Write a tremolo and it selects tremolo. Write a crescendo hairpin and the dynamics follow the wedge shape automatically, using whatever expression mechanism the library supports – continuous controllers, note expression, parameter automation – without the user knowing or caring which one. And because OVID maps canonical technique names to vendor-specific implementations, the same score plays back correctly through different sample libraries. Switch from Spitfire to Vienna Synchron and the pizzicato is still a pizzicato; the selection mechanism changes, but the musical intent is preserved. Share a piece with someone and they can listen to it as you intended it to sound, without any setup. A glissando on a harp is not a glissando on a trombone. A trill on a flute is not a trill on a kettledrum. These are musically obvious statements, but no MIDI-based system can act on them without external help. OVID knows the difference natively, because it operates at the level of musical semantics rather than note events. The Instrument Library ConnectionThis brings us back to where we started: the instrument library. The bundled library is deliberately finite – roughly 270 instruments in up to four language editions. Magnus's comparison with Igor's list is instructive, because Igor's larger catalogue was itself driven by Synth Matrices. Every instrument in that list existed because some hardware synthesiser had a patch for it, and the Synth Matrix mapped the instrument name to that patch. The noble Crwth was there not because orchestral composers regularly write for the crwth, but because a sample existed and the mapping was trivial. Remove the Synth Matrix context, and that instrument list was a reflection of available synthesiser patches, not a statement about what a notation program ought to bundle. The Ooloi instrument library serves a different function. Each instrument carries not only its notation properties – name, clef, transposition, range – but also its OVID mapping. When you drag a cor anglais from the library into your score, Ooloi knows which virtual instrument to load, which articulations are available, how to calibrate loudness against the oboe in the next staff, and how to handle the specific timbral characteristics of that instrument across your installed sample libraries. If your preferred library lacks a particular technique – col legno battuto, say – the OVID fallback chain searches your other installed libraries and finds it there. This is why the bundled library is sized the way it is. Every bundled instrument maps to an OVID profile that produces correct, calibrated, expressive playback out of the box. The library ships with OVID definitions for BBC Symphony Orchestra Discover, which is free, and Virtual Playing Orchestra as a fallback. Install both – fifteen minutes, zero cost – and every instrument in the bundled library plays back with intelligent articulation handling, loudness calibration, onset alignment, and humanisation. No DAW. No MIDI. No configuration. Humanisation deserves a word of its own. This is not random velocity variation to break up a machine-gun effect. Ooloi's humanisation applies the same principles we implemented in Igor, informed by Sundberg's research: soloists anticipate the beat; ensemble players lock to it; phrase dynamics follow natural contours; articulation affects onset timing. The intelligence is in the notation engine, not in a third-party plugin with a narrow one-second lookahead buffer. The Creative SourceI built this because I need it. I am a composer; I've written opera, orchestral music, chamber music. When I write a crescendo hairpin, I need to hear a crescendo. When I write a string tremolo, I need to hear a tremolo. I do not want to open a DAW, create tracks, assign patches, route MIDI, and draw controller curves before I can hear whether my orchestration works. That workflow is not composing; it is bookkeeping.
A DAW still has its place, of course – for final production, mixing, mastering. But the compositional workflow, the sketch, the orchestration, the moment when you need to hear whether that horn entry works against the divided violas: that must be immediate. Write the music. Press Play. Hear it as a musician would play it. Music notation is, ultimately, about music. The technology that serves it should be invisible. If you find yourself thinking about patch changes, you are no longer thinking about your piece. For who, in the end, cares about patch changes? Really? The above GIF demonstrates some of the functionality of the Instrument Library and Piece Window at this point: selection of score language, filtering on names, drag-copying, deleting, etc. What you see above is not the full 1000+ instrument selection, but a smaller library I use for development and testing. The notifications to the lower right are likewise for development.
The complete bundled instrument library is now documented.
The new guide, Instrument Library Catalogue, lists the default instrument set that ships with Ooloi: modern orchestral instruments, historical families, keyboards, plucked strings, voices, choirs, percussion, special-effect instruments, and various things that have no fixed abode but nevertheless turn up in scores. A total of roughly 270 instruments, yielding just over 1,000 language-specific library entries. The architectural decisions behind it remain where they belong, in ADR 0045: Instrument Library. This catalogue is not a theological statement about which instruments deserve to exist. It is the default library: broad, practical, and sufficient to start work. If you find yourself asking, 'You have ocarinas but not Glenfiddich Highland Pipes in G sharp?!', the answer is simple: not by default. Add them in the Instrument Library window, save them, and they are yours permanently. In other words, the bundled set is a starting point, not a border guard. Magnus's question yesterday about soprano recorder clefs sent me down a path I'd been meaning to write about. His question was straightforward: can the Instrument Library default to a treble ottava alta clef for the soprano recorder? Yes, trivially – the template carries the staff spec, you change the clef, done. But the exchange reminded me of a more consequential case where the relationship between clef and transposition isn't merely cosmetic but changes the sounding pitch of the notation itself. From roughly 1750 until well into the twentieth century, horn parts in bass clef were transposed downward from concert pitch rather than upward. For a horn in F, treble clef notation sounds a perfect fifth below the written pitch – the modern convention. But in bass clef, the same instrument's notation sounds a perfect fourth above the written pitch. The difference is an octave, and the practical consequence is that the transposition interval depends on which clef is active at any given moment in the part. This is not an obscure historical footnote. It's Beethoven, Brahms, Wagner, Strauss, Mahler, Shostakovich – the central orchestral repertoire spanning two centuries. The convention had a practical origin. Before valves, horn parts were limited to the notes of the harmonic series, and bass clef passages used only the lowest few harmonics. Writing them an octave lower than sounding pitch kept the notes within the staff when two parts shared a single staff. The convention outlived its original purpose by about a century. Ooloi's instrument definitions support clef-dependent transposition intervals. When a horn in F switches from treble to bass clef, the transposition changes accordingly – no phantom instrument changes, no hidden octave lines, no typographic compromises. The notation looks correct, the playback sounds correct, and the relationship between the two is maintained automatically.
Which is, after all, the point. Undo and redo landed a couple of days ago. The next item on the plan was the Piece Settings window – the place where a score's global configuration lives. But Piece Settings requires instrument assignments, and instrument assignments require a working Instrument Library. So the sequence revealed itself, as it does: not Piece Settings next, but the thing Piece Settings depends on. This is not an unwelcome discovery. The Instrument Library turns out to be the cleanest possible entity to build at this stage, precisely because it depends on nothing. No piece identity, no piece lifecycle, no window hierarchy. It is global and singleton: one library per backend, shared across all connected clients, persisting across restarts. It holds templates, not instances – when a musician is assigned an instrument, the piece receives a copy of the template and the two are independent from that point. Renaming a template later has no effect on instruments already in scores. That independence from the rest of the system makes it the right place to establish something that will govern every piece of shared state Ooloi ever manages: the invalidate/fetch/replace pattern. The PatternThe pattern is this. When the library changes on the backend, the server broadcasts a notification that any copies 'out there' are now stale. Clients that receive it mark their local cache stale. If the Instrument Library window happens to be open, they fetch immediately and re-render. If the window is closed, nothing happens until it opens – at which point the fetch occurs and the window renders from fresh data. A client that never opens the window pays no cost at all, even if the library is modified repeatedly during the session by other clients. The sending client follows the same path as everyone else. It does not update its local state from the success response; it waits for the event it will receive as a subscriber, then fetches like any other client. There is one code path for state updates regardless of where the change originated. In practiceWorking through the implementation surfaced several problems, each with a clean answer. Two users editing the library simultaneously must not silently overwrite each other's work, so a change is rejected if someone else updated the library first – the conflict is surfaced explicitly, and the second user reapplies their change on top of the current state. Instruments deleted by the user must stay deleted across application updates that ship new default entries, which requires tracking deletions rather than simply omitting items. Display order within a family must survive both user rearrangement and future additions from updates, which requires ordering to be stored explicitly rather than inferred from position.
What the exercise confirmed is the value of the division of concerns itself. The backend stores state, enforces consistency, and broadcasts invalidation events. The frontend gets the data when required, transforms it locally through whatever editing operations the user performs, and submits the result. The backend does not participate in editing decisions; the frontend does not manage persistence concerns. That division – established here on clean, self-contained ground – is the same division that will govern every piece of rendered state going forward. The Instrument Library is the first authoritative backend entity that is not a piece; its clean behaviour under load, concurrency, and updates confirms that the model generalises. Everything built on top of it will follow the same pattern. Read all about it in ADR 0045: Instrument Library. In which we examine why a habit of mind is mistaken for the nature of things There's a habit of mind so pervasive in software development today that it's ceased to be visible as a habit. It presents itself, rather, as common sense: ship early, iterate fast, learn from users, move fast and break things. The vocabulary is Silicon Valley but the reach is global, and it has colonised not just how software is built but how software is judged. A project that doesn't fit the pattern isn't evaluated on its own terms; it's measured against the pattern and found wanting. This is how cultural hegemony works: a local methodology, exported with the efficiency that US capitalism has always brought to the business of making its assumptions universal, ends up masquerading as common sense. The psychological mechanisms by which technical workers are recruited into this system – the mythology of meritocracy and the linguistic inflation that expands responsibility while eliminating agency – are explored at length in 'Help! Help! I'm Being Repressed! (But You're Grateful Instead). What concerns us here is a different consequence of the same hegemony: not what it does to the people inside the frame, but what it makes invisible outside it. The promise attached to the methodology (and this is what makes it effective as ideology rather than merely as practice) is that if you play by the rules, you participate in the dream. Adopt the two-week sprint, the MVP, the continuous deployment pipeline, the growth metrics, and somewhere at the end of the process stands the exit and the private jet. The methods and the mythology travel together; you don't merely acquire a development process but a tribal identity and a ready-made trajectory. The cargo cult: the rituals, performed faithfully, in the expectation that the planes will land. They mostly do not land, of course. What most people acquire is the methodology without the outcome. But this doesn't dislodge the faith, because the faith isn't really about the outcome. It's about the framework through which all technical work is now perceived. What the Lens Cannot SeeTake TeX, or the Linux kernel, or the protocols on which the internet runs. None of it was built by this method and none of it could have been. Donald Knuth spent a decade on TeX, not because he was slow, but because the problem required it. The domain had correctness conditions that couldn't be satisfied incrementally. Calling partial correctness an MVP doesn't make it one; it makes it a wrong answer with better branding. There's a further irony here that the dominant methodology prefers not to examine. Much of modern software culture sits on infrastructure built by people who worked in exactly the way it now derides: with correctness as the primary criterion and visibility as an afterthought. 'Move fast and break things' is, in this sense, parasitic: it depends for its very existence on layers of prior work whose authors would have found the phrase somewhere between baffling and contemptible. Music notation is another such domain. It's a semantic, mathematical, historical, and representational system that's been accumulating edge cases for five hundred years. Accidentals, time signatures, polytonal harmony, the memory rules that govern when a sharp must be reprinted and when it may be assumed: these are formal systems with correctness conditions, not UX choices to be iterated toward, and a notation engine that handles eighty percent of cases is simply broken. The architecture must be right before anything is visible, because the visible parts depend entirely on the invisible ones. You cannot ship a thin slice of correct rational arithmetic. You cannot gather user feedback on whether your hierarchical key signature partitioning handles organ notation correctly. The feedback loop here isn't user adoption; it's whether the semantic representation is sound enough that hard problems become tractable. These loops aren't merely operating on different timescales; they're incommensurable. User-visible behaviour and internal semantic correctness cannot be measured on the same scale, and conflating them is a category error, not merely a methodological one. The particular cruelty of the dominant methodology is that it treats foundational work as delay. Eighteen months of semantic infrastructure before a window opens is by the startup template a red flag, evidence that the team can't ship. By any other standard, it's exactly what the domain requires. The Moral DimensionThe methodological misreading would be merely irritating if it were innocent. It's not quite innocent, which is what gives it its edge. To look at a project operating outside the disruption frame and conclude that it's slow or self-indulgent requires a particular kind of incuriosity: an unwillingness to ask whether the frame itself might be the wrong instrument for the measurement. That incuriosity isn't random; it's cultivated by an intellectual monoculture that has made one historically contingent approach to software development appear to be the only conceivable one. There are people who cannot imagine a domain where the architecture must be correct before anything else is possible, because they've only ever worked in domains where it doesn't need to be. That's forgivable. But there are also people who, when presented with evidence that the domain is different, prefer the template to the evidence; a failure of intellectual range, and at some level a moral one, because it renders invisible entire categories of value, including most of the software the world actually relies on. What the Domain Actually DemandsThe disruption methodology assumes a forgiving domain: one where the cost of being wrong is low and the complexity lives in the interface rather than the semantics. Most web software fulfils these conditions reasonably well. A social media feed or a SaaS dashboard: if you get the data model slightly wrong, you refactor. If the UI is poor, you redesign. The feedback loop is fast and the penalties are recoverable. Music notation violates every one of these assumptions. The real distinction is between domains where a representational error can be repaired after the fact and domains where it metastasises, where every layer built on top of a flawed foundation inherits and amplifies the flaw, until the accumulated damage is structural and irreversible. Notation is the latter kind of domain. The semantic layer isn't a detail to be addressed after launch. The heuristics that commercial notation software relies on aren't temporary expedients awaiting a proper solution; they're the permanent consequence of foundations that made exact solutions intractable. Once that choice is made, it cannot be unmade. The technical debt is original sin, not a balance sheet entry awaiting repayment. The correct solutions exist, and not because of clever algorithms: a correct representation makes correct solutions possible. The problems didn't require heuristics. They required a foundation that sprint-cycle development philosophies, tuned for domains where being wrong is cheap and reversible, reliably select against. Music notation has been accumulating edge cases for five hundred years. It doesn't care about your sprint velocity. (This article is also available on Medium)
The documentation has accumulated to the point where it doesn't naturally sort itself for a first reader. Architecture Decision Records are numbered chronologically — in the order decisions were made, not in the order you need to encounter them. Reading straight through means confronting distributed-systems reasoning before you know what a `Piece` contains. The answer keeps arriving before you've understood the question.
There's now a guided path that reorganises the material by conceptual dependency: nine phases, starting with motivation and working through data model, language choices, addressing, pitch representation, the plugin system, rendering, and the frontend. Each phase builds the vocabulary the next one requires. Think of it as an adjunct to the Librarian — where the Oracle answers specific questions, this path builds the context that makes those answers land correctly. It's now the canonical entry point to the technical documentation. It's here. Open Settings, switch the locale. Every open window follows: menus, the About dialog, Settings itself. English to German to French to Danish, pausing on Greek. Then it repeats.
This is chrome – wiring things up, giving Ooloi a face. The obvious next step seemed to be collaboration. The architecture has supported shared backends since day one; the collaboration ticket and ADR systematise how they are handled, add authentication, authorisation, piece invitations. But you can't test the collaboration paradigm just on application settings. Theme preferences, locale, autosave interval – these are local. They don't live on a shared backend. To verify that the pattern works, you need an actual piece: something that lives on a server that one or more clients connect to. So a sequence of work comes first. Undo and redo for settings changes. Every setting change already records the old value alongside the new; the undo stack accumulates and replays inverse events. No piece dependency. This establishes the mechanism before anything more complex exists. Then creating and opening pieces — not in a naïve single-user way, but written from the start for an environment where the backend may be shared. Even locally, the model has to reflect that reality. Then undo and redo for piece content: a single authoritative stack on the server, shared across everyone editing simultaneously. The undo gesture in the frontend inspects which tier holds the more recent operation and routes accordingly. Then the Piece Settings editor, with the Instrument Library window. Here is where the collaboration pattern is actually demonstrated. Consider adjusting beam thickness or the default appearance of piano pedal extension lines: ordinary engraving decisions. Now add a collaborator with the same editor open on the same piece. Your changes appear in their view instantly. Theirs in yours. Both of you can undo, on the same data, with the same shared history. This is not a special case requiring special handling. If the preceding layers are in place, this is what falls out of the existing architecture. But it should be done as early as possible, before additional layers complicate things, so now is the right time. |
AuthorPeter Bengtson – SearchArchives
April 2026
Categories
All
|
|
|
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.
|
RSS Feed