Skip to main content

v1.9

1.9.0โ€‹

This release gives the alphaTab attribution a smaller, quieter place in the score, renders faster with about half the memory, reworks note spacing and the placement of annotations, adds per-staff control over clefs, key and time signatures and bar numbers, plays repeats and jumps in the right order, imports MusicXML files more faithfully, and loads alphaTab's core once for the page, its workers and its Audio Worklet with webpack, Rspack, Vite and Turbopack. The website is rebuilt and now lives in the alphaTab repository. The upgrade notes at the end list the visual changes, changed defaults and deprecations.

Attributionโ€‹

render: a smaller, quieter attributionโ€‹

The "rendered by alphaTab" line below the score is replaced by a small "โ™ช alphaTab.net" above the top staff at the end of the first system. It is drawn in the staff line color and adds no extra line. Songs with up to 10 bars and at most 2 tracks show no attribution at all.

Many projects hid the attribution without our consent and without crediting alphaTab elsewhere. The attribution is now part of how the score is drawn and much harder to remove; there is no setting to turn it off. If you have permission for a different credit and the new placement does not fit, get in touch.

The new Attribution page explains why we ask for credit, which alternative credits work, and offers logos and badges to download.

license: planned move to CPAL-1.0 or similarโ€‹

A future release will move from MPL-2.0 to an open-source license with an attribution clause. The choice is not settled yet; CPAL-1.0 is the best fit we see so far. alphaTab stays open source and free, also for commercial use, and releases under MPL-2.0, including this one, stay under MPL-2.0. See what changes.

Performanceโ€‹

render: faster rendering and resizingโ€‹

https://github.com/CoderLine/alphaTab/pull/2997 https://github.com/CoderLine/alphaTab/pull/2751

Compared with 1.8.4, rendering a song takes about a third less time, resizing up to 40 % less, and both allocate about half the memory. A resize now gives the same layout as a fresh render at that width. In the browser, the worker exchanges less data with the page, parts of the score far out of view release their memory, and the MIDI is generated once per load.

Full demo and all options: Responsive resize.

Music Notationโ€‹

render: power-law note spacing and last-system justificationโ€‹

https://github.com/CoderLine/alphaTab/pull/2749

alphaTab spaces notes with a power-law model, the approach Dorico, MuseScore and Finale use: doubling a duration multiplies its width by display.spacingRatio. The default is Math.SQRT2 (about 1.414, as in Dorico); values are clamped to 1.2โ€“2.0. Whole notes and rest bars follow the same ratio, so how much of a system they take depends on spacingRatio. display.stretchForce still sets the overall density.

The same four bars with spacingRatio 1.2 (first) and the default (second):

display.lastSystemFillThreshold decides when the last system stretches to the full width: once its natural width reaches the given fraction of the available width. 1 (default) never stretches it, 0 always does, and values between 0.4 and 0.7 behave like Dorico and MuseScore. It replaces display.justifyLastSystem.

Full demo and all options: Density and spacing.

Thanks to @AvaTheArchitect for the discussion that led to this.

render: effect placement against the notationโ€‹

https://github.com/CoderLine/alphaTab/pull/2750

Texts, chord names, dynamics, palm-mute and let-ring brackets and the other annotations are placed against the outline of the notation (the skyline) instead of in rows spanning the whole system. An annotation moves away from the staff only where a note, stem, beam or another annotation is in the way. Charts with many annotations need less vertical space.

00:00
00:00
\track "Guitar"
\staff {score tabs}
:8 (0.5 2.4){ch "Am" dy mf} 2.3{lr} 1.2{lr} 0.1{lr} 1.2 2.3{txt "rit."} :4 2.4 |
:8 0.6{pm} 0.6{pm} 3.6{pm} 0.6{pm} :16 12.1{txt "solo" h} 15.1{h} 12.1 14.2 :8 17.1{v} 12.1

Am and rit. sit right above the low notes of the first bar, while the high sixteenth notes in the second bar push the labels and solo up. The placement is always active. display.effectBandPaddingBottom sets the gap between an annotation row and the staff or the row below it.

Full demo and all options: Effect placement.

notation: per-staff display of clefs, key and time signatures, bar numbers and tab restsโ€‹

https://github.com/CoderLine/alphaTab/pull/2752 https://github.com/CoderLine/alphaTab/pull/2946

Each staff type (standard notation, tablature, slash and numbered notation) has its own configuration for the elements it can draw: clef, key signature, time signature, bar numbers and, on tablature, rests. Each element can be hidden, drawn only on the topmost staff type of a staff, or drawn only in the first system. You set this score-wide on the stylesheet (RenderStylesheet.scoreConfig and its siblings), per staff (Staff.scoreConfig) or per bar (Bar.scoreDisplay). The values are ElementDisplay records.

00:00
00:00
\staff {score tabs}
\staffDisplay tabs { clefVisibility false tsPlacement allStaves restsPlacement allStaves }
:4 3.3 r 0.2 1.2 | 3.2 1.2 r 0.2

The tab staff drops its TAB clef and repeats the time signature and the rests, which alphaTab otherwise draws only on the standard notation staff above it. The defaults render as before, apart from bar numbers (see the next item).

Full demo and all options: Staff element display.

notation: bar numbering with pick-up bars, custom numbers and textsโ€‹

https://github.com/CoderLine/alphaTab/pull/2907

Bar numbers belong to the master bar. Pick-up bars get no number and do not count. MasterBar.customBarNumber restarts the count, and MasterBar.customBarNumberText shows a text such as 1a instead of the number. In alphaTex, \barNumber sets either one.

00:00
00:00
\defaultBarNumberDisplay allBars
\ac :4 G4 |
:2 C5 E5 |
\barNumber "1a" :2 D5 F5 |
\barNumber 5 :1 C5

The pick-up bar has no number, the third bar shows 1a, and the last bar restarts the count at 5. By default, alphaTab now numbers only the first bar of each system. The number is centered above the start barline and no longer adds space at the start of the bar. Clef, key signature and time signature line up across the staves of a system. Multi-bar rests show their number too. The MusicXML importer reads the number attribute of each measure.

Full demo and all options: Bar numbers.

notation: tuning on the staff linesโ€‹

https://github.com/CoderLine/alphaTab/pull/2742

alphaTab can write the note name of each open string at the left end of its tab line on the first system, instead of the tuning block above the score. This matches the "tuning before staff" option in Guitar Pro. Select it with RenderStylesheet.tuningDisplayMode set to TuningDisplayMode.Staff, or with \tuningDisplayMode staff in alphaTex. display.inlineTuningPaddingRight sets the gap between the labels and the staff.

00:00
00:00
\tuningDisplayMode staff
\track "Guitar"
\staff { tabs }
\tuning (E4 B3 G3 D3 A2 D2)
:8 0.6 2.4 0.3 2.2 0.1 2.2 0.3 2.4

Guitar Pro 7 and 8 files store the mode in their stylesheet; alphaTab reads it and the Guitar Pro 7 exporter writes it.

Full demo and all options: Tuning display.

Thanks to @kulek1 for contributing this feature, and to @AvaTheArchitect for the discussion that led to it.

notation: drum tablatureโ€‹

https://github.com/CoderLine/alphaTab/pull/2591 https://github.com/CoderLine/alphaTab/pull/2990

Percussion staves can render as a drum tablature, as in Guitar Pro and TuxGuitar. Each drum piece sits on a line, and the number on the line is its articulation number. Turn it on with Staff.showTablature, or with \staff { score tabs } in alphaTex. In alphaTex, @ assigns the line of a percussion note: SnareHit@3 places the snare on line 3.

00:00
00:00
\track "Drums" { instrument percussion }
\staff { score tabs }
\clef neutral
\articulation defaults
:4 (KickHit@5 HiHatClosed@1) (SnareHit@3 HiHatClosed@1) (KickHit@5 HiHatClosed@1) (SnareHit@3 HiHatClosed@1)

Guitar Pro files show the drum tablature where the file turns it on, and Guitar Pro 7 and 8 files keep the line of every drum note on import and export.

Full demo and all options: Drum and percussion notation.

Thanks to @leocaseiro for contributing this feature, and to @sugizo for the discussion that led to it.

notation: hammer-on, pull-off and slide labels above the staffโ€‹

https://github.com/CoderLine/alphaTab/pull/2945 https://github.com/CoderLine/alphaTab/pull/2943

The H, P and sl. labels introduced in 1.8.3 are drawn above the staff instead of on the slur arcs, on standard notation, tablature and numbered notation. Each beat gets one label, centered on its slur segment; different labels on one beat stack. A segment across a system break is labeled on the first system only. Regular slurs carry no label.

Slurs between chords follow Behind Bars and Guitar Pro: on standard notation one slur joins the outer noteheads of the chord, on tablature each beat gets at most one arc above and one below. On narrow screens these slurs no longer disappear.

00:00
00:00
\staff {score tabs}
:4 r r 5.3{h} 7.3{h} | 5.3 r r (5.1{h} 5.2{sl}) | (7.1 9.2) r r r

Hide the labels with NotationElement.EffectHammerOnPullOffText and NotationElement.EffectSlideText in notation.elements.

Full demo and all options: Effects and articulations.

Thanks to @shimabox for reporting the problem with slurs between chords.

notation: centered full-bar notes and restsโ€‹

https://github.com/CoderLine/alphaTab/pull/2781

When a bar holds a single beat that lasts the whole bar, alphaTab centers it in the bar together with its annotations, following Behind Bars. This applies when every staff and voice rendered in the bar has one such beat; other bars keep the regular positioning.

00:00
00:00
\hideDynamics
:1 C5 | r.1 | \ts (3 4) :2 C5{d} | r.2{d}

Full demo and all options: Rests and full-bar notes.

Thanks to @comus111 for the discussion that led to this.

notation: rest position per beatโ€‹

https://github.com/CoderLine/alphaTab/pull/2721

A rest can take the staff position of a given pitch instead of the automatic one. In alphaTex, write the beat property restDisplayPitch; in the model, set Beat.restDisplayTone and Beat.restDisplayOctave. The position follows the clef and works per voice.

00:00
00:00
\hideDynamics
:4 r C5 r C5 | r{restDisplayPitch A5} C5 r{restDisplayPitch E4} C5

The first bar shows the automatic positions, the second bar moves the rests to A5 and E4. alphaTab does not read rest positions from Guitar Pro or MusicXML files, and the alphaTex exporter does not write restDisplayPitch.

Full demo and all options: Rests and full-bar notes.

Thanks to @roscopeeco for contributing this feature.

Other changesโ€‹

  • render: ties and slurs that continue on a new system start after the clef, key signature and time signature instead of at the left edge of the staff (#2800, thanks @GiovanniSlabs for contributing this fix)
  • render: tab staves with slashed beats render stems, beams and dots in place when notation.rhythmMode shows tab rhythm, instead of failing or drawing them at the top of the staff (#2916, thanks @zyk-mjzs)
  • render: the minimum bar width is computed correctly, and the new engraving settings beatContentPadding and barlineContentPadding keep accidentals, grace notes and flags clear of the next beat and the barline; a bar that must be squeezed below its minimum logs a warning (#2943, see Engraving clearances)
  • render: numbered notation writes rests longer than a quarter as repeated 0, voice colors reach stems, beams, flags and effects, and bend labels on one beat are stacked (#2997, see Per-element colors)
  • render: triplet feel is shown once per bar and the capo once per staff (#2992, thanks @parvanitis15)
  • render: bend and whammy annotations, grace-only bars, dense dynamics, ledger lines, string-number circles and texts of other tracks get the room they need, and adjacent trills stay separate (#2990)
  • render: dead-slapped beats, displaced unisons and rest-only beams in numbered notation no longer fail to render (#2993, #2990, thanks @yezhenbiao)

Playerโ€‹

player: repeats, alternate endings and jumps play in the right orderโ€‹

https://github.com/CoderLine/alphaTab/pull/2915 https://github.com/CoderLine/alphaTab/pull/2895 https://github.com/CoderLine/alphaTab/pull/2917 https://github.com/CoderLine/alphaTab/pull/2929

The player, the cursor and MIDI export follow one set of rules for repeats and jumps:

  • Each D.C. and D.S. is taken once. Before, a coda placed before the bar that jumps back could make playback loop forever.
  • After a jump, repeats play as their final pass: the passage plays once, with only its last alternate ending, as in MuseScore.
  • Repeat passes are counted per repeat group, so with Guitar Pro style repeat counts a repeat sign in several alternate endings plays every ending once, as in Guitar Pro 8. MusicXML files whose endings each close with a backward repeat but give no times can play fewer endings.
  • A jump inside a repeat, or on its closing bar, is taken after all repeat passes.
  • A jump on an alternate ending that playback skips is not taken.
  • MusicXML files that write jumps and markers as <sound> attributes inside a <direction>, as MuseScore exports them, play these jumps.
00:00
00:00
\track "Guitar"
\staff {score}
\ro :4 C4 D4 E4 F4 |
\ae 1 \rc 2 G4 F4 E4 D4 |
\ae 2 \jump fine G4 E4 :2 C4 |
\jump daCapoAlFine :4 A4 G4 F4 E4

This plays bars 1 2 1 3 4 1 3: after the D.C. the repeat plays as its final pass, so bar 1 continues into the second ending, where Fine ends the piece.

Full demo and all options: Repeats and structural elements.

Thanks to @AnshulJ999 and @gabbe for reporting these problems, and to @noy-solvin for contributing the fix for repeats in alternate endings.

player: pick-up bars for metronome, count-in and beamingโ€‹

https://github.com/CoderLine/alphaTab/pull/2939

alphaTab treats a pick-up bar as the end of a full bar. Beaming, triplet feel and metronome clicks follow the beats of the time signature. The count-in counts one full bar and continues up to the beat where playback starts, also when you start in the middle of a bar.

00:00
00:00
\ts (2 4)
\ac C4.8 D4.8 E4.8 |
F4.4 G4.4 |
A4.8 B4.8 C5.8 D5.8

The pick-up holds the last three eighths of a 2/4 bar: C keeps its own flag, and D and E are beamed as beat 2. The same change corrects beat timers with several tracks and tempo changes within a bar, and reading MidiFile.events with MidiFileFormat.MultiTrack no longer overflows the stack.

Full demo and all options: Count-in and metronome.

Thanks to @AlbinoBJJ for reporting this problem.

integration: separate settings for seek, range selection and click resetโ€‹

https://github.com/CoderLine/alphaTab/pull/2779

Three settings replace player.enableUserInteraction:

All three default to true. A drag creates a range only once it reaches another beat; a press and release on the same beat counts as a click, even if the mouse moved a little.

import * as alphaTab from '@coderline/alphatab';

const api = new alphaTab.AlphaTabApi(document.getElementById('alphaTab'), {
core: { file: '/scores/song.gp' },
player: {
playerMode: alphaTab.PlayerMode.EnabledAutomatic,
enableSeekToClick: true,
enablePlaybackRangeSelection: true,
resetPlaybackRangeOnClick: false,
},
});

Full demo and all options: Enabling and disabling interaction.

Thanks to @AvaTheArchitect for the discussion that led to this.

Other changesโ€‹

  • player: pausing, or switching quickly between play and pause, before the Audio Worklet has loaded no longer fails with Failed to execute 'stop' on 'AudioScheduledSourceNode' or stalls playback (#2911, thanks @kulek1)
  • player: a midiLoaded handler registered after the MIDI was loaded is called right away instead of overflowing the stack (#2928, thanks @gabbe)
  • player: a customScrollHandler is called also when player.scrollMode is Off (2889cac)
  • player: changing player.enableAnimatedBeatCursor at runtime switches the cursor (9a23e14)
  • integration: a mouse press that ends outside the score, or is lost through a window switch or an Android touch cancel, ends with one mouse-up event; before, the press stayed active, extended the selection on hover and turned off auto-scrolling (#2951, thanks @kulek1)
  • player: backing tracks and external media no longer drift behind the audio at tempos like 148 BPM (#2960, thanks @bj0rge)
  • player: after a fade out or volume swell the track plays again instead of staying silent; fades use the expression controller (CC 11) (#2995, thanks @yoyecros)
  • player: a local initialAttenuation in a SoundFont zone replaces the global value, so affected presets are no longer too quiet (#2994, thanks @fanjink)
  • player: player.scrollMode changes through updateSettings() take effect, a backing track the browser refuses to play pauses the player, audio export loads the presets it needs, and custom cursor handlers set later are attached (#2990)

alphaTex Extensionsโ€‹

alphaTex: staff display tagsโ€‹

https://github.com/CoderLine/alphaTab/pull/2946

Three tags express the staff element display settings: \defaultStaffDisplay for the whole score, \staffDisplay for the current staff and \barDisplay for the current bar. Each takes optional staff types (score, tabs, slash, numbered, several in parentheses) and a property list such as clefVisibility, tsPlacement or barNumber. The alphaTex exporter writes these settings, so they survive a round trip.

00:00
00:00
\staff {score tabs}
:4 3.3 r 0.2 1.2 |
\barDisplay tabs { tsPlacement allStaves } \ts (3 4) 3.3 0.2 r | 1.2 r 0.2

Only the change to 3/4 is restated on the tab staff.

Full demo and all options: Staff element display.

Other changesโ€‹

  • alphaTex: \barNumber sets a custom bar number or text (#2907)
  • alphaTex: \tuningDisplayMode places the tuning above the score or on the staff lines (#2742, thanks @kulek1)
  • alphaTex: the beat property restDisplayPitch positions a rest (#2721, thanks @roscopeeco)
  • alphaTex: percussion notes take their tablature line after @, as in SnareHit@3, and the exporter writes it (#2591, thanks @leocaseiro; see Drum tablature)
  • alphaTex: the note property string shows a string number on pitched notes, as in a4{string 1} (#2913, thanks @magmasystems)
  • alphaTex: harmonic values can be fractional, as in 3.3{ah 2.4}, so exported files with such values load again (#2941, thanks @stewacide)
  • alphaTex: the exporter writes acc only where the accidental changes the spelling (#2931, thanks @gabbe)
  • alphaTex: \sync accepts decimal millisecond offsets, and an export and re-import keeps empty Guitar Pro voices and drum note strings (#2960, #2997)
  • alphaTex: basicEditorLspIntegration of @coderline/alphatab-monaco answers only for its editor's model, so several editors can each use a language server, and returns a disposable; diagnosticsDelay and completionRange tune diagnostics and completions (see Monaco)
  • alphaTex: @coderline/alphatab-language-server and @coderline/alphatab-monaco bundle and run again; the language server has separate entry points for browsers and Node.js (#2830; see Language server, Monaco and the package changes)

MusicXML Extensionsโ€‹

musicxml: note spelling from step and alterโ€‹

https://github.com/CoderLine/alphaTab/pull/2931

Notes without a printed <accidental>, for example a repeated note in a bar or a note tied over the barline, were spelled from the key signature. An Fโ™ฏ in F major became a Gโ™ญ, a B in Gโ™ญ major became a Cโ™ญ, and ties joined noteheads on different staff positions. alphaTab now spells every note from <step> and <alter>, as MuseScore and Verovio do.

In bar 1 the second Fโ™ฏ stays on the F line, bars 2 and 3 tie the same notehead, and in bar 4 the B in Gโ™ญ major stays a Bโ™ฎ. The same change fixes the spellings the Guitar Pro exporter writes.

Thanks to @gabbe for reporting this problem.

musicxml: more faithful importโ€‹

Full list of supported elements: MusicXML feature table.

  • musicxml: let ring, palm mute, wedges, octave shifts, slash notation and endings are paired per part, staff and number, so they end where the file says, and let ring and palm mute are audible (#2938, thanks @ppisljar)
  • musicxml: <string> on a staff without tuning, as in classical guitar parts, becomes a string number on the pitched note instead of silencing the whole score (#2913, thanks @magmasystems)
  • musicxml: x noteheads and <play><mute> become dead notes on fretted parts, and ties on transposed staves are kept (#2914, thanks @ppisljar)
  • musicxml: <fingering> uses left-hand numbering on instruments other than piano, so a 1 is the index finger instead of the thumb (#2927, thanks @magmasystems)
  • musicxml: D.C., D.S., To Coda, Coda, Segno and Fine written as <sound> attributes inside a <direction> are played as jumps (#2929, thanks @gabbe)
  • musicxml: <metronome> with a beat unit other than a quarter, or with dots, gives the right tempo, and a <sound tempo> in the same direction takes precedence. The tempo mark shows the converted quarter-note value, for example โ™ฉ = 189 for a dotted quarter at 126 (#2910, thanks @magmasystems)
  • musicxml: harmonics written as base, touching and sounding notes, as Guitar Pro 8 exports them, become one harmonic note; in alphaTex, artificial and other harmonics on pitched notes such as C4{ah 12} sound and render (#2947, thanks @parvanitis15)
  • musicxml: notes with an <instrument> reference are treated as percussion only when that instrument is unpitched or the staff is a percussion staff (#2777, thanks @ldupoueyUB)
  • musicxml: high voice numbers are packed into consecutive voices per staff (#2831)
  • musicxml: dynamics are shown only where the file writes them, on their own staff, and apply to all staves of the part for playback (#2996, thanks @weblings)
  • musicxml: the number attribute of each measure sets custom bar numbers and texts, and implicit measures become pick-up bars (#2907; see Bar numbers)
  • musicxml: a <string> without <fret> gets its fret from the pitch, and measure-numbering holds until the file changes it (#2990)

Guitar Pro Extensionsโ€‹

exporter: files Guitar Pro opens correctlyโ€‹

https://github.com/CoderLine/alphaTab/pull/2774 https://github.com/CoderLine/alphaTab/pull/2832 https://github.com/CoderLine/alphaTab/pull/2831 https://github.com/CoderLine/alphaTab/pull/2931

Files written by the Guitar Pro 7 exporter open correctly in Guitar Pro 7 and 8:

  • The system layout is written in the form Guitar Pro expects. Before, the multi-track view of Guitar Pro 8 broke and its memory use grew without bound.
  • Every note gets a string and fret, also on staves without a tuning such as piano parts or MusicXML imports.
  • Voices beyond the four Guitar Pro supports move into free slots or are dropped with a warning, instead of crashing Guitar Pro.
  • Notes keep their spelling in every key, for example a Bโ™ญ in F major.
  • The exporter works on a copy of the score and leaves api.score unchanged.

Full demo and all options: Export to Guitar Pro 7.

Thanks to @chenkigba for contributing the system layout fix.

importer: windows-1252 decoding for Guitar Pro 3โ€“5โ€‹

https://github.com/CoderLine/alphaTab/pull/2774

Guitar Pro 3โ€“5 files store texts in the code page of the author's system. alphaTab decodes them with the new setting importer.gp3To5encoding, windows-1252 by default, so umlauts and other accented characters in titles and lyrics load correctly. A value other than utf-8 in importer.encoding still takes precedence.

Full demo and all options: Tuning importer behavior.

Thanks to @chenkigba for contributing this change.

Other changesโ€‹

  • importer/exporter: the tuning display mode of Guitar Pro 7 and 8 files is read and written (#2742, thanks @kulek1; see Tuning display)
  • importer/exporter: the drum tablature lines of Guitar Pro 7 and 8 files are kept on import and export (#2591, thanks @leocaseiro; see Drum tablature)
  • importer: a malformed GPX file fails with an error instead of looping until it runs out of memory (#2991, thanks @CaliLuke)
  • importer: Guitar Pro 3โ€“5 files read drum grace notes, note durations, fingerings, frets and MIDI channels correctly, and Guitar Pro 6 files keep ties and the track pan and volume (#2997, #2990)

Bundlers and Frameworksโ€‹

bundlers: one alphaTab core for the page, the workers and the workletโ€‹

https://github.com/CoderLine/alphaTab/pull/2998

With webpack, Rspack and Vite, the page, the Web Workers and the Audio Worklet load alphaTab's core from one shared chunk instead of a copy each, so the browser downloads and compiles about 1.2 MiB (minified) once instead of up to three times. alphaTab starts its worker with the standard new Worker(new URL('./alphaTab.worker.mjs', import.meta.url), { type: 'module' }) and its worklet from alphaTab.worklet.mjs, both importing alphaTab.core.mjs.

The new page Installing in web projects lists the setup for every bundler and framework with the number of core copies each one loads, and links to a verified sample project for each. New pages cover other bundlers, React and Next.js, Vue and Nuxt, Angular, Svelte and SvelteKit and Solid.

webpack: Rspack and Rsbuild supportโ€‹

https://github.com/CoderLine/alphaTab/pull/2998

@coderline/alphatab-webpack works with webpack 5 (5.90 or later), Rspack 1.7 and 2, and Rsbuild through tools.rspack. It bundles alphaTab's worker and worklet as entries and moves the core into an alphaTabCore split chunk. For that it sets optimization.usedExports to 'global' in production builds when you did not set it. See Installation (webpack, Rspack, Rsbuild).

vite: worker and worklet as chunks of the main buildโ€‹

https://github.com/CoderLine/alphaTab/pull/2998

@coderline/alphatab-vite emits alphaTab's worker and worklet as chunks of the main build, sharing the core chunk with the page, and supports Vite 6, 7 and 8. The URLs are written relative to the chunk that references them, so a relative base, renderBuiltUrl, SvelteKit and Nuxt 4 work. In the dev server, alphaTab is excluded from dependency pre-bundling. See Installation (Vite).

integration: entries for bundlers without a pluginโ€‹

https://github.com/CoderLine/alphaTab/pull/2998

The new exports @coderline/alphatab/core, @coderline/alphatab/worker and @coderline/alphatab/worklet let your app own alphaTab's worker and worklet entries. @coderline/alphatab/core exports the full API and starts nothing on its own; you register the worker and worklet with Environment.initializeMain. Installation (other bundlers) shows the setup for esbuild, Rollup and Parcel.

bundlers: Turbopack detectionโ€‹

https://github.com/CoderLine/alphaTab/pull/2998

alphaTab detects Turbopack (Environment.isTurbopackBundled, also printed by Environment.printEnvironmentInfo()) and starts its workers in the form Turbopack bundles, sharing the core chunk with the page. Turbopack does not bundle Audio Worklets, so there alphaTab loads its worklet from core.scriptFile. See Next.js with Turbopack.

Other changesโ€‹

  • bundlers: the minified files reference each other: alphaTab.min.mjs imports alphaTab.core.min.mjs and starts alphaTab.worker.min.mjs and alphaTab.worklet.min.mjs, which import the minified core too, so a CDN or copied setup loads only minified files.
  • player: without a detectable script file, loading the Audio Worklet fails with the error "Could not detect alphaTab script file, cannot initialize audio worklet".
  • webpack and vite: webWorkers: false turns off the worker bundling, the webpack plugin reports copy errors instead of hanging, and the Vite worker and worklet chunks are minified and no longer manifest entries (#2998, #2997, #2990)
  • bundlers: Ottavia._8va and the other enum members starting with an underscore are defined in the minified files again (#2997)

Websiteโ€‹

https://github.com/CoderLine/alphaTab/pull/2998

The website is rebuilt and moved into the alphaTab repository, so documentation and release notes now ship in the same pull request as the code. Report website problems in the alphaTab repository.

  • A new landing page with a full player and a live alphaTex editor, and a standalone Playground with track mixer, settings, export and a media sync editor.
  • A feature catalog with a demo per feature, new installation pages per bundler and framework, an Attribution page and a Showcase.
  • Site-wide choice of synthesizer or backing track and of the SoundFont, and public-domain demo songs.
  • The site builds and starts its dev server several times faster; nightlies deploy to next.alphatab.net.

Improvements & Bugfixesโ€‹

  • render: the horizontal layout with display.scale above 1 gets its full size, so the end of the score is visible and scrolls with the playhead (#2894, thanks @leocaseiro for contributing this fix and @fiskpinne for reporting it)
  • importer: Capella (.capx) files load instead of failing with "No compatible importer found for file" (Capella (CapXML))
  • platform: alphaTab reads and writes zip archives and decodes SF3 SoundFonts with its own Deflate and Vorbis implementations, so the package no longer carries four third-party license notices (#2950)
  • integration: the ICursorHandler type is exported (3d1f1bf), together with the two built-in handlers ToNextBeatAnimatingCursorHandler (used when player.enableAnimatedBeatCursor is on) and NonAnimatingCursorHandler, so a custom handler can delegate to them
  • integration: BoundsLookup.findBeats returns each beat once in the horizontal layout, errors while the worker reads a score reach the error event, and the JSON converter accepts null colors and fonts (#2997)
  • platform: fixes for the IntersectionObserver fallback, zero-width rectangles on .NET and Android, and number parsing and collections on .NET and Kotlin (#2997)

Upgrade Notesโ€‹

Visual changesโ€‹

Changed defaultsโ€‹

  • Bar numbers appear on the first bar of each system instead of on every bar (#2907). Restore numbers on every bar with \defaultBarNumberDisplay allBars in alphaTex, or set barNumber to BarNumberDisplay.AllBars on the four staff configurations of the stylesheet. See Bar numbers.
  • The engraving setting preBeatGlyphSpacing changes from 0.5 to 0.6 staff spaces (4.5 to 5.4 at the default size), and the new staffContentPadding (1 staff space) keeps the content of neighbouring staves apart (#2907).
  • Guitar Pro 3โ€“5 files are decoded with importer.gp3To5encoding, windows-1252 by default, instead of UTF-8 (#2774). Set it to utf-8 for the previous decoding. A value other than utf-8 in importer.encoding still takes precedence. See Tuning importer behavior.
  • A drag creates a playback range only once it reaches another beat, and a click that seeks while a range stays active is clamped to the range (#2779). See Enabling and disabling interaction.

Deprecationsโ€‹

The deprecated members still work.

For integrationsโ€‹

  • With @coderline/alphatab-webpack, alphaTab's core is a chunk of its own that the page loads next to your entry script. HTML generated by HtmlWebpackPlugin, HtmlRspackPlugin, Rsbuild or Next.js includes it. A hand-written <script> list must include every file of the entrypoint, and hosts that only inject chunks they know by name, such as Angular's webpack builder, set optimization.splitChunks.cacheGroups.alphaTabCore = false. See Optimization settings.
  • @coderline/alphatab-webpack sets optimization.usedExports to 'global' in production builds when you did not set it, and warns when it is true, which bundles the core twice.
  • With Vite and Rsbuild, the scripts are emitted into a subfolder (assets/, static/js/), so set core.fontDirectory to the font the plugin copies; see Point alphaTab to the font and the SoundFont.
  • Unset values of Note.fret, Note.string, Note.octave, Note.tone and Note.percussionArticulation are NaN instead of -1 (#2591). Score JSON written by 1.8 with -1 loads as unset (#2990). Replace === -1 checks with note.isStringed, note.isPercussion, note.isPiano or Number.isNaN(...). A percussion note in a drum tablature is both percussion and stringed.
  • Custom IMidiFileHandler implementations need the new member addMetronome(tick, counter, durationInTicks); handlers that write standard MIDI files can ignore the call. In pick-up bars, Automation.ratioPosition is relative to the full bar of the time signature, as Guitar Pro writes it (#2939).
  • AutomationType.Bank changes from 4 to 5; in 1.8 it had the same value as AutomationType.SyncPoint. Score JSON written by 1.8 stores bank changes as 4, which 1.9 loads as sync points (#2907).
  • Guitar Pro 3โ€“5 files: each track gets the MIDI port and channel stored in the file and its own PlaybackInformation. port is zero-based (1.8 kept the one-based value of the file), and primaryChannel can differ from 1.8, for example 2 instead of 4. Programs, volume, balance and the notes do not change, and two tracks that 1.8 played on one channel get a channel each. Code that addresses MIDI channels or ports per track sees the new numbers (#2774).
  • Settings JSON (RenderingResourcesJson) accepts the deprecated fonts copyrightFont, titleFont, subTitleFont, wordsFont, timerFont, directionsFont, fretboardNumberFont, markerFont and barNumberFont and applies them as the properties of the same name do; 1.8 ignored them in JSON. effectFont, fingeringFont and inlineFingeringFont are still accepted and still have no effect (#2749).
  • The SVG output is no longer identical between two renders of the same score: the staff lines of the bar with the attribution and the attribution itself are written as one path in a random order. Whitespace and some attributes of the SVG text changed too (#2997). The drawn result is the same. Compare rendered images instead of SVG strings.
  • The page and its alphaTab worker must load the same alphaTab version, and during a window drag only the last resize raises render events (#2997).
  • With the Audio Worklet, playerPositionChanged fires at most every 10 ms by default; player.positionUpdateIntervalInMilliseconds set to 0 restores the previous rate. Internal flow messages moved from Debug to the new LogLevel.Trace (#2997).
  • Generated MIDI fades use CC 11 instead of CC 7, and millisecond values such as sync point times keep their decimals (#2995, #2960).
  • C# and Kotlin: deprecated members are marked [Obsolete] and @Deprecated (#2990).
  • alphaTex AST consumers: the values of AlphaTexNodeType are renumbered, so compare against the enum members instead of numbers, and AlphaTexNoteNode.noteStringDot is now noteStringSeparator of type IAlphaTexStringSeparatorNode (#2591).

Package changesโ€‹

  • The npm packages carry provenance attestations from npm trusted publishing (#2959).
  • @coderline/alphatab/vite and /webpack forward to the plugin packages, and @coderline/alphatab-language-server loads with require (#2990).
  • @coderline/alphatab-vite/workerPlugin is removed. Register alphaTab() from @coderline/alphatab-vite; it covers the worker and the worklet.
  • @coderline/alphatab-vite accepts Vite ^6 || ^7 || ^8 as peer dependency.
  • @coderline/alphatab-webpack declares webpack (^5.0.0) and @rspack/core (^1.7.0 || ^2.0.0) as optional peer dependencies; install the one your project builds with.
  • @coderline/alphatab exports ./core, ./worker and ./worklet. Bundlers that resolve package exports find them without configuration; Parcel needs packageExports enabled.
  • @coderline/alphatab-webpack declares webpack as a peer dependency (^5.0.0) instead of a dependency. Install webpack in your project if it is not there yet (#2806).
  • @coderline/alphatab-language-server has separate entry points for browsers and Node.js (#2830):
    • Import startWebWorkerLanguageServer from @coderline/alphatab-language-server/server/browser and startNodeLanguageServer from @coderline/alphatab-language-server/server/node. The package root resolves to the browser entry only for bundlers that apply the browser condition; TypeScript with moduleResolution: "bundler" does not, and reports that the root has no startWebWorkerLanguageServer.
    • main, types and bin point to dist/index.node.* instead of dist/server.*. Paths into dist are not exported; use the entry points above.
    • startWebWorkerLanguageServer takes a LanguageServerMessagePort: any MessagePort, Worker or worker self fits, and its declaration type checks with either the DOM or the WebWorker library.
  • @coderline/alphatab-monaco exports its modules as subpaths: @coderline/alphatab-monaco/lsp, /lspMonacoMappings, /alphatex, /textmate, /types and /worker. Imports of @coderline/alphatab-monaco/dist/<module> keep working (see Monaco).
  • Major dependency updates: vscode-languageserver 9 to 11 in @coderline/alphatab-language-server (@coderline/alphatab-monaco now declares it too), monaco-editor 0.55 to 0.57 in @coderline/alphatab-monaco, and magic-string 0.30 to 1 in @coderline/alphatab-vite.