alphaTab Documentation

repository·develop·Indexed 23 days ago

https://github.com/coderline/alphatab

A cross-platform library for rendering music notation and guitar tablature, supporting Guitar Pro and MusicXML formats with built-in MIDI synthesis. The ecosystem includes the alphaTex language for music definition, a Language Server (LSP) for coding assistance, Monaco Editor integration, and a development playground for exercising API capabilities.

Tokens
24.3K
Snippets
36
Records
103
Agent score
83%

What's inside alphaTab

  1. Overview of alphaTab

    develop

    alphaTab is a cross-platform music notation and guitar tablature rendering library. It allows developers to load and display music sheets from various data sources within websites or native applications.

    Key capabilities include:

    • Data Loading: Supports Guitar Pro (3-7), AlphaTex (built-in markup language), and MusicXML.
    • Rendering: Supports SVG and Raster graphics (using HTML5 canvas, GDI+, SkiaSharp, or Android Canvas depending on the platform).
    • Notation Support: Renders standard music notation and guitar tablatures, including complex elements like repeats, alternate endings, tunings, clefs, time signatures, dynamics, and various guitar-specific techniques (vibrato, bends, slides, etc.).
    • Audio Playback: Includes a built-in MIDI+SoundFont2 synthesizer named alphaSynth for playing music sheets via HTML5 Web Audio, NAudio, or Android AudioTrack.
  2. Overview of alphaTex Language Definitions

    develop

    The alphaTex package contains the central language definitions for alphaTex. These definitions serve as the single source of truth for:

    1. Metadata tags: What tags exist in the language.
    2. Parameters: What parameters each tag supports.
    3. Types and Documentation: The data types and descriptions for language elements.

    These definitions are consumed by three main components:

    • The alphaTab parser (via generated code).
    • The alphaTab Language Server (to provide coding assistance).
    • The alphaTex documentation website (to describe available elements).

    Note that while this package defines the structure of the language, it does not include the logic for mapping the Abstract Syntax Tree (AST) to the data model or vice versa. That logic is handled by the AlphaTex1LanguageHandler.

  3. What is the alphaTab Language Server?

    develop

    The alphaTab Language Server (LSP) provides coding assistance for writing alphaTex. It is designed to be integrated into code editors to improve the developer experience when working with alphaTex files.

    Key features include:

    • Basic Syntax Highlighting: Visualizes code structure.
    • Hover Documentation: Provides context-sensitive information when hovering over code elements.
    • Code Completion: Suggests alphaTex commands and values.
    • Signature Help for Value Lists: Assists in completing specific value lists within commands.
    • Formatter: Automatically structures and cleans up alphaTex code.
  4. Explore alphaTab Playground Demos

    develop

    The playground includes several demos that exercise different parts of the alphaTab API:

    DemoPathKey Features
    Controldemos/control/Full player: sidebar, transport bar, downloads, drag-drop, layout/scroll/zoom pickers.
    Drum Recorderdemos/recorder/Programmatic score construction, dynamic system extension, MIDI extension/regeneration, playedBeatChanged.
    AlphaTex Editordemos/alphatex-editor/AlphaTex source $\leftrightarrow$ Score model round-tripping via AlphaTexImporter/AlphaTexExporter with Monaco LSP.
    YouTube Syncdemos/youtube-sync/EnabledExternalMedia player mode driving alphaTab from a YouTube IFrame player.
    Visual Test Resultsdemos/test-results/Diff viewer for visual regression failures with accept-to-reference flow.
  5. Integrate alphaTab with Monaco Editor

    develop

    The @coderline/alphatab-monaco package provides integration for the Monaco Editor to support writing alphaTex. It enables coding assistance through three primary integration levels:

    1. TextMate Grammars: Sets up Monaco to use TextMate grammars for syntax highlighting.
    2. Basic alphaTex Support: Provides a basic alphaTex language configuration, including a grammar and language settings.
    3. Language Server Integration: Enables full coding assistance by integrating with an alphaTab Language Server running in a web worker.
    WARNING

    This package is still in a very experimental stage.

  6. Compose UI using Primitives and Composers

    develop

    The playground architecture uses two layers of components:

    1. Primitives: Generic, alphaTab-unaware UI bricks (e.g., IconButton, Slider, Dropdown). They take props in their constructor and expose typed methods and callbacks.
    2. Composers: alphaTab-aware components (e.g., TransportBar, Footer). They take the AlphaTabApi in their constructor, declare a layout template with cmp-... placeholders, and mount primitives into those placeholders. They translate engine events into primitive method calls.

    Composition Mechanics:

    • Static Layout: Use parseHtml to define a template with cmp-... placeholders, then use mount(parent, '.cmp-x', component) to swap placeholders for the component's .root.
    • Dynamic Layout: For lists or runtime-dependent content, declare a container in the template and use appendChild to add component roots directly.
    // Static layout example
    this.root = parseHtml(html`
        <div class="at-footer">
            <div class="cmp-waveform"></div>
            <div class="cmp-time-slider"></div>
            <div class="cmp-transport"></div>
        </div>
    `);
    this.waveform = mount(this.root, '.cmp-waveform', new Waveform(api));
    this.timeSlider = mount(this.root, '.cmp-time-slider', new TimeSlider(api));
    this.transport = mount(this.root, '.cmp-transport', new TransportBar(api));
    
    // Dynamic layout example
    this.root = parseHtml(html`<div class="at-track-list"></div>`);
    api.scoreLoaded.on(score => {
        for (const item of this.items) item.dispose();
        this.items = [];
        for (const track of score.tracks) {
            const item = new TrackItem(api, track);
            this.root.appendChild(item.root);
            this.items.push(item);
        }
    });
  7. Understand the Transpiler IR and Pipeline

    develop

    The Intermediate Representation (IR) is the central data structure used by the transpiler to bridge the gap between TypeScript source and the final C# or Kotlin output.

    The Pipeline Stages

    The IR moves through three distinct stages during every emission process:

    1. AstTransformer: Performs a per-file walk of the TypeScript source to produce a raw IR SourceFile for every TypeScript root. This is the only stage allowed to allocate new tsSymbol-backed nodes.
    2. PassPipeline: Executes named, whole-program passes that mutate the IR in place (e.g., resolve-types, rewrite-visibilities).
    3. AstPrinter: Performs a per-file walk to emit the final .cs or .kt text. This stage is read-only and does not mutate the IR.

    Importing the IR

    To work with the IR definitions, import them using the following pattern:

    import * as cs from '../src/ir/Ir'

    Note: The cs alias is a historical convention; the namespace is the canonical IR shared by all targets.

    import * as cs from '../src/ir/Ir'
  8. Extend editors with alphaTab LSP modules

    develop

    Beyond the core Language Server, the @coderline/alphatab-language-server package provides additional modules to help implement full editor support:

    • TextMate Grammar: Use this for basic tokenizing and syntax highlighting in editors that support TextMate grammars (like VS Code).
    • Technical/Reference Documentation: Use the provided alphaTex documentation for implementing hover hints or user-help features within an editor.
  9. IR Invariants for the Printer Stage

    develop

    For the AstPrinter to function correctly, the following invariants must be satisfied by the IR before it enters the printing stage:

    1. No UnresolvedTypeNode: Every TypeNode reachable from a SourceFile must be a concrete kind (e.g., PrimitiveTypeNode, ArrayTypeNode, MapTypeNode, ArrayTupleNode, FunctionTypeNode, TypeReference, or a NamedTypeDeclaration).
    2. Parent Links: Every node must have a parent (with the exception of specific paren-wrapping logic).
    3. Override Propagation: After rewrite-visibilities, every method/property overriding a virtual base must have isOverride: true or isVirtual: true if it is an override target.
    4. Naming Conventions: All identifier strings on member-access nodes must have already been processed by the target's toMethodNameCase or toPropertyNameCase.
    5. Smart-cast Lowering: Any expression requiring runtime type narrowing must be wrapped by SmartCastResolver. Printers do not perform their own type inference.
  10. Understand the alphaTab Playground component contract

    develop

    The playground uses a framework-agnostic, class-based component model. Every UI piece implements the Mountable interface and follows these rules:

    1. Constructor: Takes engine dependencies (like alphaTab.AlphaTabApi) and props. It builds the DOM detached as .root. It never takes a parent argument.
    2. Parent → Child (Push API): Parents communicate with children via public methods, such as setReady(ready: boolean).
    3. Child → Parent (Event API): Children communicate with parents via assignable callback fields (e.g., onPlayClick: (() => void) | null = null).
    4. Lifecycle: The dispose() method must release all resources, including alphaTab event subscriptions (the () => void returned by api.event.on(...)), DOM listeners, intervals, and child components.
    5. State: The AlphaTabApi is the single source of truth. Components subscribe directly to engine events rather than maintaining intermediate state containers.
    class Transport implements Mountable {
        readonly root: HTMLElement;            // detached at construction; mounted by caller
    
        constructor(api: alphaTab.AlphaTabApi); // engine deps as args; never `parent`
    
        setReady(ready: boolean): void;         // parent → child push API
        onSomething: (() => void) | null = null; // child → parent event API
    
        dispose(): void;
    }
  11. Use Noto Sans Variable or Static fonts

    develop

    The Noto Sans font package provides both variable and static font files.

    Variable Fonts

    If your application supports variable fonts, you can use the single files located in the Noto_Sans/ directory. These files contain multiple styles controlled by two axes:

    • wdth (width)
    • wght (weight)

    Variable Font Files:

    • Noto_Sans/NotoSans-VariableFont_wdth,wght.ttf
    • Noto_Sans/NotoSans-Italic-VariableFont_wdth,wght.ttf

    Using variable fonts allows you to select intermediate styles that are not available in the static versions.

    Static Fonts

    If your application does not support variable fonts, use the individual static font files located in the Noto_Sans/static/ directory. These files represent specific, fixed styles (e.g., NotoSans_Condensed-Bold.ttf).

  12. Use component-local styling and naming conventions

    develop

    To prevent CSS leaks and ID collisions, follow these naming conventions:

    • No IDs: Do not use id attributes inside component markup. Use class names or data-* attributes instead.
    • Kebab-prefixed classes: Prefix every component class with its kebab name (e.g., at-icon-btn, at-transport-...).
    • Local nesting: Keep nested selectors component-local (e.g., .at-track .at-track-controls instead of a bare .at-track-controls).
    • Placeholder markers: Use cmp-<slot> classes inside composer templates to mark locations for mount() to replace.