# ABC Tools: MusicXML → Notation Pipeline

## 1. Architecture at a glance

`abctools.html` is a thin shell that loads a stack of libraries and one large app script:

| Layer | File | Role |
|---|---|---|
| UI shell | `abctools.html` | Toolbar, editor textarea, notation container divs |
| App logic | `app.js` / `app-min.js` | File I/O, editor wiring, render orchestration, playback, PDF/website export |
| MusicXML↔ABC converter | `xml2abc.js` / `xml2abc-min.js` | Parses a MusicXML DOM and emits ABC notation text |
| Notation engine | `abcjs-basic-eskin.js` (a customized fork of [abcjs](https://github.com/paulrosen/abcjs)) | Parses **ABC** text, lays out engraving, renders SVG, drives Web Audio playback |
| Archive/encoding helpers | `jszip.js`, browser `FileReader`/`TextDecoder` | Unzips `.mxl`, detects/decodes character encoding |
| Editor | `codemirror.js` + `simple.js` | Syntax highlighting/editing of the ABC text, debounced change events |

**Key architectural fact: MusicXML is never rendered directly.** It is always first translated into ABC notation text, and ABC is the single internal representation that drives everything downstream — rendering, playback, transposition, tablature, and PDF export.

```
MusicXML/.mxl file
       │
       ▼
  xml2abc.js  (vertaal)  ──►  ABC text  ──►  abcjs (ABCJS.renderAbc)  ──►  SVG notation
                                   │                    │
                                   ▼                    ▼
                            CodeMirror editor      Web Audio playback
                             (source of truth)      (ABCJS.synth)
```

## 2. Getting a MusicXML file in

Entry point: `DoFileRead(file, callback)` in `app.js`.

1. **Extension sniffing** — `.xml`/`.musicxml` vs `.mxl` vs `.mid` vs `.bww` are branched separately.
2. **`.mxl` (compressed MusicXML)** is a zip container: `JSZip` opens it, reads `META-INF/container.xml` to find the `rootfile` path, then extracts that inner `.xml` entry as text.
3. **Encoding/format normalization** — raw bytes are read via `FileReader.readAsArrayBuffer`, then `decodeFileToUnicodeString()` sniffs the encoding (falls back through UTF‑8/Windows‑1252), the text is Unicode-normalized (NFC), and `checkForMissingXMLHeader()` patches files that are missing the `<?xml ...?>` prolog (a MuseScore/some-exporter quirk).
4. **Format detection** — `isXML(theText)` checks whether the payload is really MusicXML (vs. plain ABC or BWW bagpipe notation, which take other code paths).

## 3. The actual conversion: `xml2abc.js`

This is a JS port of Willem Vree's Python `xml2abc` converter. Entry point is `vertaal(xmltree, options)` (Dutch for "translate"), called from `app.js`'s `importMusicXML()`:

```js
var xmldata = $.parseXML(theXML);     // browser DOMParser via jQuery
var result  = vertaal(xmldata, gMusicXMLImportOptions);
var abcText = result[0];
```

Internally `vertaal()`:
- Builds a `Parser` object that walks the DOM with jQuery selectors (`$p.find('measure')`, etc.) — no dependency on a schema-validating XML library, just tree traversal.
- **`Parser.parse()`** iterates `<part>` → `<measure>` → child elements in document order, dispatching on tag name:
  - `<note>` → `doNote()` — reads pitch (`<step>`/`<octave>`/`<alter>`), duration, accidentals, ties, beams, chord flag, grace notes, ornaments/articulations, lyrics.
  - `<attributes>` → `doAttr()` — key signature, time signature, clef, divisions-per-quarter-note (needed to convert MusicXML's tick-based durations into ABC's fractional note lengths via `abcdur()`).
  - `<direction>` → dynamics, tempo markings, text directions.
  - `<harmony>` → chord symbols.
  - `<barline>` → repeats/voltas.
  - `<backup>`/`<forward>` → multi-voice time cursor adjustments (MusicXML lets voices/staves interleave via explicit backward/forward duration jumps; the parser mirrors that with `msc.incTime()`).
- Pitch is converted to ABC letter+octave notation via `staffStep()`/`addoct()`, respecting the running key signature and any "passing" accidentals per measure (`curalts`).
- A `Music` object (`this.msc`) accumulates per-voice note/bar events; `outVoice()` and `sortMeasure()` order and format them (including broken-rhythm shorthand, tuplets via `insTup()`).
- Finally `ABCoutput` (`abcOut`) serializes the accumulated voices into ABC header fields (`X:`, `T:`, `M:`, `L:`, `K:`, voice defs) plus the note body — this is the `.abc` text returned to `app.js`.

Back in `app.js`, `importMusicXML()` does a few post-processing passes on the emitted ABC text: stripping redundant inline clef markers, injecting a `Q:` tempo field if requested, handling a custom `I:linebreak` directive, deriving a tune title from the filename if MusicXML had none, and normalizing stacked-chord notation. The result is inserted into the CodeMirror editor as plain ABC text — **at this point the MusicXML is fully discarded**; only the ABC text persists as the document's source of truth.

## 4. Rendering ABC → notation

Editor changes flow through a debounced CodeMirror `"changes"` listener → `OnABCTextChange()`/`RenderAsync()` → `Render()` → `RenderTheNotes()`:

```js
var params = GetABCJSParams(instrument);   // engraving/tab options for the active tab (Notation/Mandolin/Guitar/…)
var visualObj = ABCJS.renderAbc(renderDivs, tune, params);
```

`ABCJS.renderAbc()` (inside the bundled, Eskin-customized `abcjs` engine) does its own independent parse of the ABC text — tokenizing pitches/durations/decorations — and produces:
- One or more `visualObj` tune objects (abstract music model: voices, beams, ties, measures).
- SVG markup written directly into the `notation<N>` `<div>`s in `#notation-holder`.

The same `tune` (ABC) string, not the original MusicXML, is what gets rendered for every alternate "tab" view (Names, Mandolin, GDAD, Guitar, Uke, Whistle, etc.) — those are just different `params`/clef/tuning configurations passed to the same `renderAbc()` call, since abcjs supports rendering fretted/fingering tablature alongside or instead of standard notation.

**Raw/highlighting mode**: when enabled, `params.clickListener` and `selectTypes` wire up bidirectional mapping between SVG notation elements and ranges of ABC source text, so clicking a note highlights its ABC text and vice versa.

## 5. Playback

Uses the same rendered `visualObj` plus `ABCJS.synth`:
```js
var midiBuffer = new ABCJS.synth.CreateSynth(theABC);
synthControl = new ABCJS.synth.SynthController(theABC);
synthControl.setTune(visualObj, userAction, audioParams);
```
abcjs converts its internal note model to a Web Audio schedule (with soundfont samples for piano/percussion loaded from `acoustic_grand_piano-mp3.js` / `percussion-mp3.js`), so no MIDI file round-trip is needed for playback — it plays directly off the parsed ABC.

## 6. Round-trips and other formats

- **ABC → MusicXML** (`ExportMusicXML`/`SaveABCAsMusicXML`) goes the other direction using abcjs's `CreateMusicXML` capability — useful for the "Reformat Using MusicXML" round-trip feature and MusicXML export.
- **MIDI import** posts the file to an external service that returns MusicXML, which then re-enters the exact same `importMusicXML()` path.
- **BWW (bagpipe) import** uses a separate `bww2abc.js` converter straight to ABC, bypassing xml2abc entirely.
- **PDF export** renders each tune's SVG (via the same `renderAbc` call against an offscreen div) and composites pages with `jsPDF`/`pdf-lib`.

## TL;DR

MusicXML support is essentially a **format adapter**, not a parallel rendering path: `xml2abc.js` is a MusicXML→ABC transpiler, and everything the tool does — display, transposition, tablature, playback, PDF — operates uniformly on ABC text via the abcjs engraving/audio engine.
