midiviz

How SWAM and the Joshua Bell Violin choose articulations

Research brief, 19 Oct 2026, for #034. The question: how do Audio Modeling’s SWAM Solo Strings and Embertone’s Joshua Bell Violin decide by themselves whether a note is played legato, détaché, staccato or with a slide, and what can #034 take from that?

Sources:

1. Both do it, from the same three cues

Both instruments are played live from a keyboard, and both read the same cues. SWAM’s manual puts it in one sentence: “Staccato, legato, portamento and bow-change articulations are managed by a special algorithm which takes into account note velocity, the interval between the notes, and the time between note-off and the subsequent note-on.”

Cue SWAM JBV
Overlap (next note-on before this note-off) legato inside one bow; with Mono SX, crossing to an adjacent string stops the old string (#034 has this) true legato, from recorded transitions (three styles × intervals beyond an octave)
Gap (note-off, then note-on) détaché: a new bow. After “a short interval” the next stroke starts on the Bow Start direction bow change on every detached note
Velocity of an overlapped note high: legato; low: portamento, slower the lower. The threshold is “Port/Leg Speed&Thresh” quiet overlapped notes slide (portamento)
Velocity of a detached note the attack’s strength (“Accent”, “Attack: Vel. Soft / Hard / Mix”) the dynamic and the attack; “Adaptive Shorts”: velocity sets how short a staccato is
Note length / release — “Quick Release”: a short note picks staccato / spiccato / ricochet samples, so it waits a “Global Lag Window” to see the note-off
Repeated pitch — a quick repeat becomes a “Rebow” (a new bow on the same note) automatically
Speed — “Adaptive Legato”: the transition gets shorter the faster you play. “Speed” can drive any control
Expression at zero an automatic bow change when the expression rests at 0 —
Chords “Auto” polyphony waits a short look-ahead to tell a double stop from a single note “Multi-Stop Attacks”: 3–4 notes roll (1-2, 2-1, 2-2, 1-1-2) with a set delay

Both pay for the guessing with latency on a live keyboard. JBV’s “Global Lag Window” waits for the note-off, and SWAM adds latency to staccato notes in Auto mode. Sound On Sound notes “a small lag … while the script figures out what’s going on”.

JBV’s Intuition page adds tendencies on top of the rules, all randomised by sliders:

SWAM’s comparable controls are Random Bow, Random Finger, Vibrato Random, Vibrato Fade-In and “Dynamic Transit.” (the dynamic’s shape through a legato transition).

2. Why their rules alone would not work for #034

The rules assume the MIDI carries the player’s articulation in its note lengths: overlaps for slurs, gaps for separate bows. Our MIDI files don’t. Over the 48 violin MIDIs in violinist/midis/ (40,988 consecutive note pairs in the solo track):

Next note starts … share
before this one ends (overlap) 1.9 %
exactly when it ends (touching) 94.9 %
after a gap under 15 % of the interval 1.7 %
after a gap of 15–45 % 0.6 %
after a longer gap 1.0 %

They are score exports (Mutopia, MuseScore, LilyPond): every note is written at its full value, so slurs, staccato dots and bowings are gone. The exceptions are a few files that shorten notes (Paganini’s Caprice 24, half the notes; the Kreutzer, 7 % long gaps) and Bach’s slow movements, where overlapping notes are voices in a chord. To SWAM, “touching” counts as détaché (note-off before note-on), so it would bow every note separately. That is the machine-gun result the manuals warn about.

So #034 has to infer articulation from the music, as a violinist reading an unmarked part would. In return it has what a live instrument doesn’t: the whole piece in advance, so no lag window is needed and decisions can look ahead.

3. What #034 does today

Not there yet: the choice of how many notes share a bow, staccato and spiccato as kinds of stroke, re-bowing repeated notes, legato transitions whose speed follows the tempo, explicit articulation when a file does carry it, and pitch instability that grows with speed and interval.

4. Proposal: an articulation planner

A step between fingering and buildMotion that labels every note: slur group, stroke type and transition. Two layers.

Layer 1: read the file when it says something (SWAM’s and JBV’s rules, applied offline):

Layer 2: infer when the file is silent (the 95 % case), from rules a violinist would use. Each rule needs checking against marked editions before it is trusted:

How to check it. Mutopia’s LilyPond sources for the same pieces contain the slurs and dots our MIDIs lost (( ) slurs, -. staccato). That gives ground truth for nearly every file in violinist/midis/ without hand labelling:

A planner that reaches, say, 75 % slur agreement on Bach’s Partitas would already be well beyond today’s fixed rule.

Effort. Layer 1 is small: rules on durations and velocities, plus tests. Layer 2 with the LilyPond evaluation is the larger part: a slur parser for Mutopia .ly files, alignment to the MIDI notes, and rule tuning, probably a day.

5. What not to copy

6. Status (19 Oct 2026)

Layers 1 and 2 are built (strings/articulation.js), with MusicXML / .mxl score input (strings/score.js). Mutopia’s ground truth turned out to be unnecessary for a first check: the Bach Violin Dataset’s MusicXML editions already carry slurs. The results are in strings/README.md: planner F1 50 % / agreement 68 % against the fixed rule’s 39 % / 60 %.

Since then:

Details are in the strings README.